From 0621a8eff15206ad92cd77f8ea3e7b7c72563a12 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Tue, 5 Jul 2022 13:17:50 +0200 Subject: [PATCH] Fix concurrency issues in FreeMarkerMacroTests Prior to this commit, tests in these two classes intermittently failed with errors similar to the following, due to concurrent modification of shared files. expected: "" but was: " "hidden"/>" This commit fixes this by creating a new temporary folder for each test method invocation. --- .../view/freemarker/FreeMarkerMacroTests.java | 35 +++++--- .../view/freemarker/FreeMarkerMacroTests.java | 89 ++++++++++--------- 2 files changed, 71 insertions(+), 53 deletions(-) diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerMacroTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerMacroTests.java index ad50b9658c..b160c631b9 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerMacroTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/view/freemarker/FreeMarkerMacroTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,10 @@ package org.springframework.web.reactive.result.view.freemarker; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -32,7 +33,6 @@ import reactor.core.publisher.Mono; import org.springframework.beans.testfixture.beans.TestBean; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.FileSystemResource; import org.springframework.http.MediaType; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.ModelMap; @@ -45,6 +45,7 @@ import org.springframework.web.server.ServerWebExchange; import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest; import org.springframework.web.testfixture.server.MockServerWebExchange; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.singletonMap; import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; @@ -66,12 +67,17 @@ public class FreeMarkerMacroTests { private Configuration freeMarkerConfig; + private Path templateLoaderPath; + + @BeforeEach public void setUp() throws Exception { + this.templateLoaderPath = Files.createTempDirectory("webflux-").toAbsolutePath(); + this.applicationContext.refresh(); FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); - configurer.setTemplateLoaderPaths("classpath:/", "file://" + System.getProperty("java.io.tmpdir")); + configurer.setTemplateLoaderPaths("classpath:/", "file://" + this.templateLoaderPath); this.freeMarkerConfig = configurer.createConfiguration(); } @@ -333,13 +339,8 @@ public class FreeMarkerMacroTests { return getOutput(); } - private String fetchMacro(String name) throws Exception { - ClassPathResource resource = new ClassPathResource(TEMPLATE_FILE, getClass()); - assertThat(resource.exists()).isTrue(); - String all = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream())); - all = all.replace("\r\n", "\n"); - String[] macros = StringUtils.delimitedListToStringArray(all, "\n\n"); - for (String macro : macros) { + private static String fetchMacro(String name) throws Exception { + for (String macro : loadMacros()) { if (macro.startsWith(name)) { return macro.substring(macro.indexOf("\n")).trim(); } @@ -347,9 +348,17 @@ public class FreeMarkerMacroTests { return null; } + private static String[] loadMacros() throws IOException { + ClassPathResource resource = new ClassPathResource(TEMPLATE_FILE, FreeMarkerMacroTests.class); + assertThat(resource.exists()).isTrue(); + String all = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream())); + all = all.replace("\r\n", "\n"); + return StringUtils.delimitedListToStringArray(all, "\n\n"); + } + private void storeTemplateInTempDir(String macro) throws IOException { - FileSystemResource resource = new FileSystemResource(System.getProperty("java.io.tmpdir") + "/tmp.ftl"); - FileCopyUtils.copy("<#import \"spring.ftl\" as spring />\n" + macro, new FileWriter(resource.getPath())); + Files.write(this.templateLoaderPath.resolve("tmp.ftl"), + ("<#import \"spring.ftl\" as spring />\n" + macro).getBytes(UTF_8)); } private List getOutput() { diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/FreeMarkerMacroTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/FreeMarkerMacroTests.java index 6db737d433..51f0a9b4fb 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/FreeMarkerMacroTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/view/freemarker/FreeMarkerMacroTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,13 @@ package org.springframework.web.servlet.view.freemarker; -import java.io.FileWriter; +import java.io.IOException; import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; -import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; @@ -34,7 +35,6 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.testfixture.beans.TestBean; import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.FileSystemResource; import org.springframework.util.FileCopyUtils; import org.springframework.util.StringUtils; import org.springframework.web.context.support.StaticWebApplicationContext; @@ -49,6 +49,7 @@ import org.springframework.web.testfixture.servlet.MockHttpServletRequest; import org.springframework.web.testfixture.servlet.MockHttpServletResponse; import org.springframework.web.testfixture.servlet.MockServletContext; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; /** @@ -61,35 +62,34 @@ public class FreeMarkerMacroTests { private static final String TEMPLATE_FILE = "test.ftl"; - private StaticWebApplicationContext wac; + private final StaticWebApplicationContext wac = new StaticWebApplicationContext(); - private MockHttpServletRequest request; + private final MockServletContext servletContext = new MockServletContext(); - private MockHttpServletResponse response; + private final MockHttpServletRequest request = new MockHttpServletRequest(); - private FreeMarkerConfigurer fc; + private final MockHttpServletResponse response = new MockHttpServletResponse(); + + private final FreeMarkerConfigurer fc = new FreeMarkerConfigurer(); + + private Path templateLoaderPath; @BeforeEach public void setUp() throws Exception { - ServletContext sc = new MockServletContext(); - wac = new StaticWebApplicationContext(); - wac.setServletContext(sc); + this.templateLoaderPath = Files.createTempDirectory("servlet-").toAbsolutePath(); - // final Template expectedTemplate = new Template(); - fc = new FreeMarkerConfigurer(); - fc.setTemplateLoaderPaths("classpath:/", "file://" + System.getProperty("java.io.tmpdir")); - fc.setServletContext(sc); + fc.setTemplateLoaderPaths("classpath:/", "file://" + this.templateLoaderPath); + fc.setServletContext(servletContext); fc.afterPropertiesSet(); + wac.setServletContext(servletContext); wac.getDefaultListableBeanFactory().registerSingleton("freeMarkerConfigurer", fc); wac.refresh(); - request = new MockHttpServletRequest(); request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac); request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, new AcceptHeaderLocaleResolver()); request.setAttribute(DispatcherServlet.THEME_RESOLVER_ATTRIBUTE, new FixedThemeResolver()); - response = new MockHttpServletResponse(); } @@ -203,12 +203,12 @@ public class FreeMarkerMacroTests { @Test public void testForm1() throws Exception { - assertThat(getMacroOutput("FORM1")).isEqualTo(""); + assertThat(getMacroOutput("FORM1")).isEqualTo(""); } @Test public void testForm2() throws Exception { - assertThat(getMacroOutput("FORM2")).isEqualTo(""); + assertThat(getMacroOutput("FORM2")).isEqualTo(""); } @Test @@ -225,27 +225,27 @@ public class FreeMarkerMacroTests { @Test public void testForm9() throws Exception { - assertThat(getMacroOutput("FORM9")).isEqualTo(""); + assertThat(getMacroOutput("FORM9")).isEqualTo(""); } @Test public void testForm10() throws Exception { - assertThat(getMacroOutput("FORM10")).isEqualTo(""); + assertThat(getMacroOutput("FORM10")).isEqualTo(""); } @Test public void testForm11() throws Exception { - assertThat(getMacroOutput("FORM11")).isEqualTo(""); + assertThat(getMacroOutput("FORM11")).isEqualTo(""); } @Test public void testForm12() throws Exception { - assertThat(getMacroOutput("FORM12")).isEqualTo(""); + assertThat(getMacroOutput("FORM12")).isEqualTo(""); } @Test public void testForm13() throws Exception { - assertThat(getMacroOutput("FORM13")).isEqualTo(""); + assertThat(getMacroOutput("FORM13")).isEqualTo(""); } @Test @@ -266,7 +266,7 @@ public class FreeMarkerMacroTests { @Test public void testForm17() throws Exception { - assertThat(getMacroOutput("FORM17")).isEqualTo(""); + assertThat(getMacroOutput("FORM17")).isEqualTo(""); } @Test @@ -282,9 +282,7 @@ public class FreeMarkerMacroTests { private String getMacroOutput(String name) throws Exception { String macro = fetchMacro(name); assertThat(macro).isNotNull(); - - FileSystemResource resource = new FileSystemResource(System.getProperty("java.io.tmpdir") + "/tmp.ftl"); - FileCopyUtils.copy("<#import \"spring.ftl\" as spring />\n" + macro, new FileWriter(resource.getPath())); + storeTemplateInTempDir(macro); DummyMacroRequestContext rc = new DummyMacroRequestContext(request); Map msgMap = new HashMap<>(); @@ -324,23 +322,15 @@ public class FreeMarkerMacroTests { view.setUrl("tmp.ftl"); view.setExposeSpringMacroHelpers(false); view.setConfiguration(config); - view.setServletContext(new MockServletContext()); + view.setServletContext(servletContext); view.render(model, request, response); - // tokenize output and ignore whitespace - String output = response.getContentAsString(); - output = output.replace("\r\n", "\n"); - return output.trim(); + return getOutput(); } - private String fetchMacro(String name) throws Exception { - ClassPathResource resource = new ClassPathResource("test.ftl", getClass()); - assertThat(resource.exists()).isTrue(); - String all = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream())); - all = all.replace("\r\n", "\n"); - String[] macros = StringUtils.delimitedListToStringArray(all, "\n\n"); - for (String macro : macros) { + private static String fetchMacro(String name) throws Exception { + for (String macro : loadMacros()) { if (macro.startsWith(name)) { return macro.substring(macro.indexOf("\n")).trim(); } @@ -348,4 +338,23 @@ public class FreeMarkerMacroTests { return null; } + private static String[] loadMacros() throws IOException { + ClassPathResource resource = new ClassPathResource("test.ftl", FreeMarkerMacroTests.class); + assertThat(resource.exists()).isTrue(); + String all = FileCopyUtils.copyToString(new InputStreamReader(resource.getInputStream())); + all = all.replace("\r\n", "\n"); + return StringUtils.delimitedListToStringArray(all, "\n\n"); + } + + private void storeTemplateInTempDir(String macro) throws IOException { + Files.write(this.templateLoaderPath.resolve("tmp.ftl"), + ("<#import \"spring.ftl\" as spring />\n" + macro).getBytes(UTF_8)); + } + + private String getOutput() throws IOException { + String output = response.getContentAsString(); + output = output.replace("\r\n", "\n").replaceAll(" +"," "); + return output.trim(); + } + }