This is an automated email from the ASF dual-hosted git repository.
sdanilov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new b1128c227e IGNITE-18970 Allow WorkDirectoryExtension to preserve work
directories of specific tests (#1753)
b1128c227e is described below
commit b1128c227edc07489a5045c269466f6c1c544407
Author: Semyon Danilov <[email protected]>
AuthorDate: Tue Mar 7 14:10:20 2023 +0400
IGNITE-18970 Allow WorkDirectoryExtension to preserve work directories of
specific tests (#1753)
---
.../testframework/WorkDirectoryExtensionTest.java | 135 ++++++++++++++++++++-
.../testframework/WorkDirectoryExtension.java | 111 ++++++++++++++---
2 files changed, 228 insertions(+), 18 deletions(-)
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/testframework/WorkDirectoryExtensionTest.java
b/modules/core/src/test/java/org/apache/ignite/internal/testframework/WorkDirectoryExtensionTest.java
index d56f78ef1e..0ab278b651 100644
---
a/modules/core/src/test/java/org/apache/ignite/internal/testframework/WorkDirectoryExtensionTest.java
+++
b/modules/core/src/test/java/org/apache/ignite/internal/testframework/WorkDirectoryExtensionTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.testframework;
import static
org.apache.ignite.internal.testframework.JunitExtensionTestUtils.assertExecutesSuccessfully;
import static
org.apache.ignite.internal.testframework.JunitExtensionTestUtils.assertExecutesWithFailure;
+import static
org.apache.ignite.internal.testframework.WorkDirectoryExtension.keepWorkDirPropertyValid;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.not;
@@ -31,8 +32,10 @@ import static
org.junit.platform.testkit.engine.TestExecutionResultConditions.me
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
+import org.apache.ignite.internal.util.IgniteUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
@@ -204,16 +207,33 @@ class WorkDirectoryExtensionTest {
private static Path file2;
+ private static Path file3;
+
+ private static final String TMP_PATH;
+
+ static {
+ try {
+ TMP_PATH = Files.createTempDirectory("testdir").toString();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
@AfterAll
- static void verify() throws IOException {
+ static void verify() {
assertTrue(Files.exists(file1));
assertFalse(Files.exists(file2));
+ assertFalse(Files.exists(file3));
+ assertTrue(Files.exists(Paths.get(TMP_PATH)));
- Files.delete(file1);
+ IgniteUtils.deleteIfExists(file1.getParent());
+ IgniteUtils.deleteIfExists(Paths.get(TMP_PATH));
+
+ System.clearProperty(WorkDirectoryExtension.ARTIFACT_DIR_PROPERTY);
}
@SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
- @WithSystemProperty(key =
WorkDirectoryExtension.KEEP_WORK_DIR_PROPERTY, value = "true")
+ @WithSystemProperty(key =
WorkDirectoryExtension.KEEP_WORK_DIR_PROPERTY, value =
"SystemPropertiesTest.test1")
@Test
void test1(@WorkDirectory Path workDir) throws IOException {
file1 = Files.createFile(workDir.resolve("foo"));
@@ -224,6 +244,83 @@ class WorkDirectoryExtensionTest {
void test2(@WorkDirectory Path workDir) throws IOException {
file2 = Files.createFile(workDir.resolve("foo"));
}
+
+ @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
+ @WithSystemProperty(key =
WorkDirectoryExtension.KEEP_WORK_DIR_PROPERTY, value =
"SystemPropertiesTest.test3")
+ @Test
+ void test3(@WorkDirectory Path workDir) throws IOException {
+ file3 = Files.createFile(workDir.resolve("foo"));
+
+ System.setProperty(WorkDirectoryExtension.ARTIFACT_DIR_PROPERTY,
TMP_PATH);
+ }
+ }
+
+ /**
+ * Test class for the {@link #testSystemPropertyWithStaticWorkDir()} test.
+ */
+ @ExtendWith(SystemPropertiesExtension.class)
+ @ExtendWith(WorkDirectoryExtension.class)
+ @WithSystemProperty(key = WorkDirectoryExtension.KEEP_WORK_DIR_PROPERTY,
value = "SystemPropertiesTestWithStaticWorkDir")
+ static class SystemPropertiesTestWithStaticWorkDir {
+ private static Path file1;
+
+ private static Path file2;
+
+ @WorkDirectory
+ static Path workDir;
+
+ @AfterAll
+ static void verify() {
+ assertTrue(Files.exists(file1));
+ assertTrue(Files.exists(file2));
+
+ IgniteUtils.deleteIfExists(file1.getParent());
+ }
+
+ @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
+ @Test
+ void test1() throws IOException {
+ file1 = Files.createFile(workDir.resolve("foo"));
+ }
+
+ @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
+ @Test
+ void test2() throws IOException {
+ file2 = Files.createFile(workDir.resolve("bar"));
+ }
+ }
+
+ /**
+ * Test class for the {@link #testSystemPropertyWithMultipleTests()} test.
+ */
+ @ExtendWith(SystemPropertiesExtension.class)
+ @ExtendWith(WorkDirectoryExtension.class)
+ @WithSystemProperty(key = WorkDirectoryExtension.KEEP_WORK_DIR_PROPERTY,
value = "SystemPropertiesTestWithMultipleTests.test1,"
+ + "SystemPropertiesTestWithMultipleTests.test2")
+ static class SystemPropertiesTestWithMultipleTests {
+ private static Path file1;
+
+ private static Path file2;
+
+ @AfterAll
+ static void verify() {
+ assertTrue(Files.exists(file1));
+ assertTrue(Files.exists(file2));
+
+ IgniteUtils.deleteIfExists(file1.getParent());
+ }
+
+ @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
+ @Test
+ void test1(@WorkDirectory Path workDir) throws IOException {
+ file1 = Files.createFile(workDir.resolve("foo"));
+ }
+
+ @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
+ @Test
+ void test2(@WorkDirectory Path workDir) throws IOException {
+ file2 = Files.createFile(workDir.resolve("bar"));
+ }
}
/**
@@ -234,6 +331,38 @@ class WorkDirectoryExtensionTest {
assertExecutesSuccessfully(SystemPropertiesTest.class);
}
+ /**
+ * Tests that a static work directory can be preserved when a special
system property is set.
+ */
+ @Test
+ void testSystemPropertyWithStaticWorkDir() {
+
assertExecutesSuccessfully(SystemPropertiesTestWithMultipleTests.class);
+ }
+
+ /**
+ * Tests that a static work directory can be preserved when a special
system property is set.
+ */
+ @Test
+ void testSystemPropertyWithMultipleTests() {
+
assertExecutesSuccessfully(SystemPropertiesTestWithMultipleTests.class);
+ }
+
+ /**
+ * Tests {@link WorkDirectoryExtension#keepWorkDirPropertyValid}.
+ */
+ @Test
+ void testKeepWorkDirectoryPattern() {
+ assertTrue(keepWorkDirPropertyValid("Foo"));
+ assertTrue(keepWorkDirPropertyValid("Foo.bar"));
+ assertTrue(keepWorkDirPropertyValid("Foo,Foo"));
+ assertTrue(keepWorkDirPropertyValid("Foo.bar,Foo"));
+ assertTrue(keepWorkDirPropertyValid("Foo.bar,Foo.bar"));
+
+ assertFalse(keepWorkDirPropertyValid("Foo#bar"));
+ assertFalse(keepWorkDirPropertyValid("Foo.bar, Foo"));
+ assertFalse(keepWorkDirPropertyValid("Foo ,Foo.bar"));
+ }
+
/**
* Test class for the {@link #testEmptyClass()} test.
*/
diff --git
a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/WorkDirectoryExtension.java
b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/WorkDirectoryExtension.java
index 213f160d87..ef45afd5fe 100644
---
a/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/WorkDirectoryExtension.java
+++
b/modules/core/src/testFixtures/java/org/apache/ignite/internal/testframework/WorkDirectoryExtension.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.testframework;
+import static java.util.stream.Collectors.toSet;
import static
org.apache.ignite.internal.testframework.IgniteTestUtils.isWindowsOs;
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace;
@@ -26,9 +27,16 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
+import java.util.regex.Pattern;
import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
import org.apache.ignite.internal.util.IgniteUtils;
import org.apache.ignite.lang.IgniteSystemProperties;
import org.jetbrains.annotations.Nullable;
@@ -61,8 +69,8 @@ import
org.junit.platform.commons.support.HierarchyTraversalMode;
* </ol>
*
* <p>Temporary folders are removed after tests have finished running, but
this behaviour can be controlled by setting the
- * {@link WorkDirectoryExtension#KEEP_WORK_DIR_PROPERTY} property to {@code
true}, in which case the created folder can
- * be kept intact for debugging purposes.
+ * {@link WorkDirectoryExtension#KEEP_WORK_DIR_PROPERTY} property. See {@link
#KEEP_WORK_DIR_PROPERTY} and {@link #ARTIFACT_DIR_PROPERTY}
+ * for more information.
*/
public class WorkDirectoryExtension
implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback,
AfterEachCallback, ParameterResolver {
@@ -70,16 +78,30 @@ public class WorkDirectoryExtension
private static final Namespace NAMESPACE =
Namespace.create(WorkDirectoryExtension.class);
/**
- * System property that, when set to {@code true}, will make the extension
preserve the created directories. Default is {@code false}.
+ * System property that can be used to provide a comma-separated list of
test names whose work directories should be preserved after
+ * test execution. Test name consists of test class name, a dot and a test
method name. In case if work directory is injected into the
+ * static field and is shared between different tests, only test class
name should be put into the list.
+ * <br>
+ * Example: {@code
"FooBarTest.test1,FooBarTest.test2,StaticWorkDirectoryFieldTest,FooBarTest.test3"}.
+ * Default value is {@code null}.
*/
public static final String KEEP_WORK_DIR_PROPERTY = "KEEP_WORK_DIR";
+ /**
+ * System property that denotes the directory where archived work
directory of the test, kept using {@link #KEEP_WORK_DIR_PROPERTY},
+ * should be saved in. If defined, original work directory will be
deleted. Default value is {@code null}.
+ */
+ public static final String ARTIFACT_DIR_PROPERTY = "ARTIFACT_DIR";
+
/** Base path for all temporary folders in a module. */
private static final Path BASE_PATH = getBasePath();
/** Name of the work directory that will be injected into {@link
BeforeAll} methods or static members. */
private static final String STATIC_FOLDER_NAME = "static";
+ /** Pattern for the {@link #KEEP_WORK_DIR_PROPERTY}. */
+ private static final Pattern PATTERN =
Pattern.compile("\\b\\w+(?:\\.\\w+)?(?:,\\b\\w+(?:\\.\\w+)?)*\\b");
+
/**
* Creates and injects a temporary directory into a static field.
*/
@@ -99,7 +121,7 @@ public class WorkDirectoryExtension
/** {@inheritDoc} */
@Override
public void afterAll(ExtensionContext context) throws Exception {
- removeWorkDir(context);
+ cleanupWorkDir(context);
Path testClassDir = getTestClassDir(context);
@@ -133,7 +155,7 @@ public class WorkDirectoryExtension
/** {@inheritDoc} */
@Override
public void afterEach(ExtensionContext context) throws Exception {
- removeWorkDir(context);
+ cleanupWorkDir(context);
}
/** {@inheritDoc} */
@@ -212,11 +234,77 @@ public class WorkDirectoryExtension
/**
* Removes a previously created work directory.
*/
- private static void removeWorkDir(ExtensionContext context) {
+ private static void cleanupWorkDir(ExtensionContext context) {
Path workDir =
context.getStore(NAMESPACE).remove(context.getUniqueId(), Path.class);
- if (workDir != null && shouldRemoveDir()) {
- IgniteUtils.deleteIfExists(workDir);
+ String testClassName = context.getRequiredTestClass().getSimpleName();
+
+ String testName = context.getTestMethod().map(method -> testClassName
+ "." + method.getName()).orElse(testClassName);
+
+ if (workDir != null) {
+ if (shouldKeepWorkDir(testName)) {
+ String artifactDir =
IgniteSystemProperties.getString(ARTIFACT_DIR_PROPERTY);
+
+ if (artifactDir != null) {
+ Path artifactDirPath = Paths.get(artifactDir, testName +
".zip");
+
+ zipDirectory(workDir, artifactDirPath);
+
+ IgniteUtils.deleteIfExists(workDir);
+ }
+ } else {
+ IgniteUtils.deleteIfExists(workDir);
+ }
+ }
+ }
+
+ private static boolean shouldKeepWorkDir(String testName) {
+ String keepWorkDirStr =
IgniteSystemProperties.getString(KEEP_WORK_DIR_PROPERTY);
+
+ Set<String> keepWorkDirForTests;
+
+ if (keepWorkDirStr != null) {
+ if (!keepWorkDirPropertyValid(keepWorkDirStr)) {
+ throw new IllegalArgumentException(KEEP_WORK_DIR_PROPERTY + "
value " + keepWorkDirStr + " doesn't match pattern");
+ }
+
+ keepWorkDirForTests =
Arrays.stream(keepWorkDirStr.split(",")).collect(toSet());
+ } else {
+ keepWorkDirForTests = Collections.emptySet();
+ }
+
+ return keepWorkDirForTests.contains(testName);
+ }
+
+ static boolean keepWorkDirPropertyValid(String property) {
+ return PATTERN.matcher(property).matches();
+ }
+
+ private static void zipDirectory(Path source, Path target) {
+ try {
+ Files.createDirectories(target.getParent());
+
+ Files.createFile(target);
+
+ try (var zs = new ZipOutputStream(Files.newOutputStream(target))) {
+ try (Stream<Path> filesStream = Files.walk(source)) {
+ filesStream.filter(path -> !Files.isDirectory(path))
+ .forEach(path -> {
+ var zipEntry = new
ZipEntry(source.relativize(path).toString());
+ try {
+ zs.putNextEntry(zipEntry);
+
+ Files.copy(path, zs);
+
+ zs.closeEntry();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
}
@@ -250,13 +338,6 @@ public class WorkDirectoryExtension
return fields.get(0);
}
- /**
- * Returns {@code true} if the extension should remove the created
directories.
- */
- private static boolean shouldRemoveDir() {
- return !IgniteSystemProperties.getBoolean(KEEP_WORK_DIR_PROPERTY);
- }
-
/**
* Returns {@code true} if the given directory is empty or {@code false}
if the given directory contains files or does not exist.
*/