test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java
branchJDK-8200758-branch
changeset 58648 3bf53ffa9ae7
parent 58464 d82489644b15
child 58696 61c44899b4eb
equal deleted inserted replaced
58647:2c43b89b1679 58648:3bf53ffa9ae7
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 
    23 
    24 package jdk.jpackage.test;
    24 package jdk.jpackage.test;
    25 
    25 
       
    26 import java.lang.reflect.Array;
    26 import java.lang.reflect.Method;
    27 import java.lang.reflect.Method;
    27 import java.nio.file.Files;
    28 import java.nio.file.Files;
    28 import java.util.Collections;
    29 import java.nio.file.Path;
    29 import java.util.List;
    30 import java.util.*;
       
    31 import java.util.function.Predicate;
       
    32 import java.util.function.Supplier;
    30 import java.util.stream.Collectors;
    33 import java.util.stream.Collectors;
    31 import java.util.stream.Stream;
    34 import java.util.stream.Stream;
    32 import jdk.jpackage.test.Functional.ThrowingConsumer;
    35 import jdk.jpackage.test.Functional.ThrowingConsumer;
    33 import jdk.jpackage.test.Functional.ThrowingFunction;
    36 import jdk.jpackage.test.Functional.ThrowingFunction;
    34 import jdk.jpackage.test.Functional.ThrowingRunnable;
    37 import jdk.jpackage.test.Functional.ThrowingRunnable;
    35 import jdk.jpackage.test.Functional.ThrowingSupplier;
    38 
    36 
    39 final class TestInstance implements ThrowingRunnable {
    37 class TestInstance implements ThrowingRunnable {
       
    38 
    40 
    39     static class TestDesc {
    41     static class TestDesc {
    40         private TestDesc() {
    42         private TestDesc() {
    41         }
    43         }
    42 
    44 
    43         String testFullName() {
    45         String testFullName() {
    44             StringBuilder sb = new StringBuilder();
    46             StringBuilder sb = new StringBuilder();
    45             sb.append(clazz.getSimpleName());
    47             sb.append(clazz.getSimpleName());
       
    48             if (instanceArgs != null) {
       
    49                 sb.append('(').append(instanceArgs).append(')');
       
    50             }
    46             if (functionName != null) {
    51             if (functionName != null) {
    47                 sb.append('.');
    52                 sb.append('.');
    48                 sb.append(functionName);
    53                 sb.append(functionName);
    49                 if (args != null) {
    54                 if (functionArgs != null) {
    50                     sb.append('(').append(args).append(')');
    55                     sb.append('(').append(functionArgs).append(')');
    51                 }
    56                 }
    52             }
    57             }
    53             return sb.toString();
    58             return sb.toString();
    54         }
    59         }
    55 
    60 
    56         private Class clazz;
    61         static Builder createBuilder() {
    57         private String functionName;
    62             return new Builder();
    58         private String args;
    63         }
    59 
    64 
    60         private static TestDesc create() {
    65         static final class Builder implements Supplier<TestDesc> {
    61             TestDesc desc = new TestDesc();
    66             private Builder() {
    62             desc.clazz = enclosingMainMethodClass();
    67             }
    63             return desc;
    68 
       
    69             Builder method(Method v) {
       
    70                 method = v;
       
    71                 return this;
       
    72             }
       
    73 
       
    74             Builder ctorArgs(Object... v) {
       
    75                 ctorArgs = ofNullable(v);
       
    76                 return this;
       
    77             }
       
    78 
       
    79             Builder methodArgs(Object... v) {
       
    80                 methodArgs = ofNullable(v);
       
    81                 return this;
       
    82             }
       
    83 
       
    84             @Override
       
    85             public TestDesc get() {
       
    86                 TestDesc desc = new TestDesc();
       
    87                 if (method == null) {
       
    88                     desc.clazz = enclosingMainMethodClass();
       
    89                 } else {
       
    90                     desc.clazz = method.getDeclaringClass();
       
    91                     desc.functionName = method.getName();
       
    92                     desc.functionArgs = formatArgs(methodArgs);
       
    93                     desc.instanceArgs = formatArgs(ctorArgs);
       
    94                 }
       
    95                 return desc;
       
    96             }
       
    97 
       
    98             private static String formatArgs(List<Object> values) {
       
    99                 if (values == null) {
       
   100                     return null;
       
   101                 }
       
   102                 return values.stream().map(v -> {
       
   103                     if (v != null && v.getClass().isArray()) {
       
   104                         return String.format("%s(length=%d)",
       
   105                                 Arrays.deepToString((Object[]) v),
       
   106                                 Array.getLength(v));
       
   107                     }
       
   108                     return String.format("%s", v);
       
   109                 }).collect(Collectors.joining(", "));
       
   110             }
       
   111 
       
   112             private static List<Object> ofNullable(Object... values) {
       
   113                 List<Object> result = new ArrayList();
       
   114                 for (var v: values) {
       
   115                     result.add(v);
       
   116                 }
       
   117                 return result;
       
   118             }
       
   119 
       
   120             private List<Object> ctorArgs;
       
   121             private List<Object> methodArgs;
       
   122             private Method method;
    64         }
   123         }
    65 
   124 
    66         static TestDesc create(Method m, Object... args) {
   125         static TestDesc create(Method m, Object... args) {
    67             TestDesc desc = new TestDesc();
   126             TestDesc desc = new TestDesc();
    68             desc.clazz = m.getDeclaringClass();
   127             desc.clazz = m.getDeclaringClass();
    69             desc.functionName = m.getName();
   128             desc.functionName = m.getName();
    70             if (args.length != 0) {
   129             if (args.length != 0) {
    71                 desc.args = Stream.of(args).map(Object::toString).collect(
   130                 desc.functionArgs = Stream.of(args).map(v -> {
    72                         Collectors.joining(","));
   131                     if (v.getClass().isArray()) {
       
   132                         return String.format("%s(length=%d)",
       
   133                                 Arrays.deepToString((Object[]) v),
       
   134                                 Array.getLength(v));
       
   135                     }
       
   136                     return String.format("%s", v);
       
   137                 }).collect(Collectors.joining(", "));
    73             }
   138             }
    74             return desc;
   139             return desc;
    75         }
   140         }
       
   141 
       
   142         private Class clazz;
       
   143         private String functionName;
       
   144         private String functionArgs;
       
   145         private String instanceArgs;
    76     }
   146     }
    77 
   147 
    78     TestInstance(ThrowingRunnable testBody) {
   148     TestInstance(ThrowingRunnable testBody) {
    79         assertCount = 0;
   149         assertCount = 0;
    80         this.testConstructor = (unused) -> null;
   150         this.testConstructor = (unused) -> null;
    81         this.testBody = (unused) -> testBody.run();
   151         this.testBody = (unused) -> testBody.run();
    82         this.beforeActions = Collections.emptyList();
   152         this.beforeActions = Collections.emptyList();
    83         this.afterActions = Collections.emptyList();
   153         this.afterActions = Collections.emptyList();
    84         this.testDesc = TestDesc.create();
   154         this.testDesc = TestDesc.createBuilder().get();
    85     }
   155         this.dryRun = false;
    86 
   156     }
    87     TestInstance(ThrowingFunction testConstructor, MethodCall testBody,
   157 
    88             List<ThrowingConsumer> beforeActions,
   158     TestInstance(MethodCall testBody, List<ThrowingConsumer> beforeActions,
    89             List<ThrowingConsumer> afterActions) {
   159             List<ThrowingConsumer> afterActions, boolean dryRun) {
    90         assertCount = 0;
   160         assertCount = 0;
    91         this.testConstructor = testConstructor;
   161         this.testConstructor = v -> ((MethodCall)v).newInstance();
    92         this.testBody = testBody;
   162         this.testBody = testBody;
    93         this.beforeActions = beforeActions;
   163         this.beforeActions = beforeActions;
    94         this.afterActions = afterActions;
   164         this.afterActions = afterActions;
    95         this.testDesc = testBody.createDescription();
   165         this.testDesc = testBody.createDescription();
       
   166         this.dryRun = dryRun;
    96     }
   167     }
    97 
   168 
    98     void notifyAssert() {
   169     void notifyAssert() {
    99         assertCount++;
   170         assertCount++;
   100     }
   171     }
   131         if (skippedTestException != null) {
   202         if (skippedTestException != null) {
   132             throw skippedTestException;
   203             throw skippedTestException;
   133         }
   204         }
   134     }
   205     }
   135 
   206 
       
   207     Path workDir() {
       
   208         Path result = Path.of(".");
       
   209         List<String> components = new ArrayList<>();
       
   210 
       
   211         String testFunctionName = functionName();
       
   212         if (testFunctionName != null) {
       
   213             components.add(testFunctionName);
       
   214         }
       
   215 
       
   216         if (isPrametrized()) {
       
   217             components.add(String.format("%08x", fullName().hashCode()));
       
   218         }
       
   219 
       
   220         if (!components.isEmpty()) {
       
   221             result = result.resolve(String.join(".", components));
       
   222         }
       
   223 
       
   224         return result;
       
   225     }
       
   226 
       
   227     boolean isPrametrized() {
       
   228         return Stream.of(testDesc.functionArgs, testDesc.instanceArgs).anyMatch(
       
   229                 Objects::nonNull);
       
   230     }
       
   231 
   136     @Override
   232     @Override
   137     public void run() throws Throwable {
   233     public void run() throws Throwable {
   138         final String fullName = testDesc.testFullName();
   234         final String fullName = fullName();
   139         TKit.log(String.format("[ RUN      ] %s", fullName));
   235         TKit.log(String.format("[ RUN      ] %s", fullName));
   140         try {
   236         try {
   141             Object testInstance = testConstructor.apply(testBody);
   237             Object testInstance = testConstructor.apply(testBody);
   142             beforeActions.forEach((a) -> ThrowingConsumer.toConsumer(a).accept(
   238             beforeActions.forEach(a -> ThrowingConsumer.toConsumer(a).accept(
   143                     testInstance));
   239                     testInstance));
   144             Files.createDirectories(TKit.workDir());
       
   145             try {
   240             try {
   146                 testBody.accept(testInstance);
   241                 if (!dryRun) {
       
   242                     Files.createDirectories(workDir());
       
   243                     testBody.accept(testInstance);
       
   244                 }
   147             } finally {
   245             } finally {
   148                 afterActions.forEach(a -> TKit.ignoreExceptions(() -> a.accept(
   246                 afterActions.forEach(a -> TKit.ignoreExceptions(() -> a.accept(
   149                         testInstance)));
   247                         testInstance)));
   150             }
   248             }
   151             status = Status.Passed;
   249             status = Status.Passed;
   153             if (skippedTestException != null) {
   251             if (skippedTestException != null) {
   154                 status = Status.Skipped;
   252                 status = Status.Skipped;
   155             } else if (status == null) {
   253             } else if (status == null) {
   156                 status = Status.Failed;
   254                 status = Status.Failed;
   157             }
   255             }
       
   256 
       
   257             if (!KEEP_WORK_DIR.contains(status)) {
       
   258                 TKit.deleteDirectoryRecursive(workDir());
       
   259             }
       
   260 
   158             TKit.log(String.format("%s %s; checks=%d", status, fullName,
   261             TKit.log(String.format("%s %s; checks=%d", status, fullName,
   159                     assertCount));
   262                     assertCount));
   160         }
   263         }
   161     }
   264     }
   162 
   265 
   194     private final TestDesc testDesc;
   297     private final TestDesc testDesc;
   195     private final ThrowingFunction testConstructor;
   298     private final ThrowingFunction testConstructor;
   196     private final ThrowingConsumer testBody;
   299     private final ThrowingConsumer testBody;
   197     private final List<ThrowingConsumer> beforeActions;
   300     private final List<ThrowingConsumer> beforeActions;
   198     private final List<ThrowingConsumer> afterActions;
   301     private final List<ThrowingConsumer> afterActions;
       
   302     private final boolean dryRun;
       
   303 
       
   304     private final static Set<Status> KEEP_WORK_DIR = Functional.identity(
       
   305             () -> {
       
   306                 final String propertyName = "keep-work-dir";
       
   307                 Set<String> keepWorkDir = TKit.tokenizeConfigProperty(
       
   308                         propertyName);
       
   309                 if (keepWorkDir == null) {
       
   310                     return Set.of(Status.Failed);
       
   311                 }
       
   312 
       
   313                 Predicate<Set<String>> isOneOf = options -> {
       
   314                     return !Collections.disjoint(keepWorkDir, options);
       
   315                 };
       
   316 
       
   317                 Set<Status> result = new HashSet<>();
       
   318                 if (isOneOf.test(Set.of("pass", "p"))) {
       
   319                     result.add(Status.Passed);
       
   320                 }
       
   321                 if (isOneOf.test(Set.of("fail", "f"))) {
       
   322                     result.add(Status.Failed);
       
   323                 }
       
   324 
       
   325                 return Collections.unmodifiableSet(result);
       
   326             }).get();
       
   327 
   199 }
   328 }