eclipse-ee4j / jakartaee-tck-tools

Other
7 stars 15 forks source link

com.sun.ts.tests.ejb30.assembly.librarydirectory.custom.Client is throwing com.sun.ts.tests.ejb30.common.helper.TestFailedException #53

Closed starksm64 closed 1 month ago

starksm64 commented 2 months ago

The com.sun.ts.tests.ejb30.assembly.librarydirectory.custom.Client is throwing a custom com.sun.ts.tests.ejb30.common.helper.TestFailedException, and this breaks the code generation as the overriden method does not have the correct throws clause.

If there are going to be a non-trivial number of custom exceptions on test methods, we will need to update the api to take the method name and exception type to throw, e.g., something like:

public class TestMethodInfo {
    private String methodName;
    // fully qualified class name of the throws type
    private String throwsException;
}

and then TestPackageInfoBuilder#buildTestPackgeInfo would be:

public TestPackageInfo buildTestPackgeInfo(Class<?> clazz, List<TestMethodInfo> testMethods) throws IOException;

Here is the Client code:

/*
 * Copyright (c) 2007, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

/*
 * $Id$
 */

package com.sun.ts.tests.ejb30.assembly.librarydirectory.custom;

import com.sun.javatest.Status;
import com.sun.ts.tests.ejb30.assembly.common.ClientBase;
import com.sun.ts.tests.ejb30.assembly.common.Util;
import com.sun.ts.tests.ejb30.common.helper.TestFailedException;
import com.sun.ts.tests.ejb30.misc.getresource.common.GetResourceTest;

public class Client extends ClientBase {
  private static final String RESOURCE_NAME = "foo.txt";

  private static final String RESOURCE_NAME_AT_ROOT = "/foo.txt";

  private static final String RESOURCE_NAME_AT_COMMON_DIR = "/com/sun/ts/tests/ejb30/assembly/common/foo.txt";

  private static final String SECOND_LEVEL_JAR_RESOURCE_NAME = "second-level-jar.txt";

  private static final String SECOND_LEVEL_JAR_RESOURCE_CONTENT = SECOND_LEVEL_JAR_RESOURCE_NAME;

  private static final String SECOND_LEVEL_DIR_RESOURCE_NAME = "second-level-dir.txt";

  private static final String SECOND_LEVEL_DIR_RESOURCE_CONTENT = SECOND_LEVEL_DIR_RESOURCE_NAME;

  public static void main(String[] args) {
    Client theTests = new Client();
    Status s = theTests.run(args, System.out, System.err);
    s.exit();
  }

  /*
   * @testName: libDirNotUsed
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: EAR/lib/*.jar are not included in classpath, since
   * <library-directory> is set to something else
   */
  public void libDirNotUsed() throws TestFailedException {
    Util.verifyGetResource(getClass(), RESOURCE_NAME, null);
    Util.verifyGetResource(getClass(), RESOURCE_NAME_AT_ROOT, null);
    Util.verifyGetResource(getClass(), RESOURCE_NAME_AT_COMMON_DIR, null);
  }

  /*
   * @testName: libDirNotUsedEJB
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: EAR/lib/*.jar are not included in classpath, since
   * <library-directory> is set to something else
   */
  public void libDirNotUsedEJB() throws TestFailedException {
    Util.verifyResource(remoteAssemblyBean, RESOURCE_NAME, null,
        remoteAssemblyBean.getResource(RESOURCE_NAME));
    Util.verifyResource(remoteAssemblyBean, RESOURCE_NAME_AT_ROOT, null,
        remoteAssemblyBean.getResource(RESOURCE_NAME_AT_ROOT));
    Util.verifyResource(remoteAssemblyBean, RESOURCE_NAME_AT_COMMON_DIR, null,
        remoteAssemblyBean.getResource(RESOURCE_NAME_AT_COMMON_DIR));
  }

  /*
   * @testName: secondLevelJar
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: EAR/lib/*.jar may have further Class-Path dependencies
   */
  public void secondLevelJar() throws TestFailedException {
    (new GetResourceTest()).getResourceWithClass(getClass(),
        SECOND_LEVEL_JAR_RESOURCE_NAME, SECOND_LEVEL_JAR_RESOURCE_CONTENT);
  }

  /*
   * @testName: secondLevelJarEJB
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: EAR/lib/*.jar may have further Class-Path dependencies
   */
  public void secondLevelJarEJB() throws TestFailedException {
    String result = remoteAssemblyBean
        .getResourceContent(SECOND_LEVEL_JAR_RESOURCE_NAME);
    GetResourceTest.verify(result, SECOND_LEVEL_JAR_RESOURCE_CONTENT);
  }

  /*
   * @testName: secondLevelDir
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: EAR/lib/*.jar may have further Class-Path dependencies
   */
  public void secondLevelDir() throws TestFailedException {
    (new GetResourceTest()).getResourceWithClass(getClass(),
        SECOND_LEVEL_DIR_RESOURCE_NAME, SECOND_LEVEL_DIR_RESOURCE_CONTENT);
  }

  /*
   * @testName: secondLevelDirEJB
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: EAR/lib/*.jar may have further Class-Path dependencies
   */
  public void secondLevelDirEJB() throws TestFailedException {
    String result = remoteAssemblyBean
        .getResourceContent(SECOND_LEVEL_DIR_RESOURCE_NAME);
    GetResourceTest.verify(result, SECOND_LEVEL_DIR_RESOURCE_CONTENT);
  }

  /*
   * @testName: postConstructInvokedInSuperElseWhere
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: PostConstruct method must be invoked even when it's in a
   * superclass not packaged in appclient-client.jar
   */

  /*
   * @testName: remoteAdd
   * 
   * @assertion_ids:
   * 
   * @test_Strategy:
   */

  /*
   * @testName: remoteAddByHelloEJB
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: hello ejb is packaged as a standalone ejb module and
   * deployed separately. It client view jar is packaged inside current ear and
   * referenced by both appclient and ejb jar thru MANIFEST.MF appclient ->
   * helloBean
   */

  /*
   * @testName: remoteAddByHelloEJBFromAssemblyBean
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: hello ejb is packaged as a standalone ejb module and
   * deployed separately. It client view jar is packaged inside current ear and
   * referenced by both appclient and ejb jar thru MANIFEST.MF appclient ->
   * assemblyBean -> helloBean
   */
}
starksm64 commented 2 months ago

@scottmarlow is it easy enough to get the throws type?

One potential problem I see with this example is that there are testName comments in the com.sun.ts.tests.ejb30.assembly.librarydirectory.custom.Client class that refer to methods in the com.sun.ts.tests.ejb30.assembly.common.ClientBase base class. For example, the remoteAddByHelloEJBFromAssemblyBean method. The base class method does use a different throws type, and is marked with the testName tag in the method comment:

  /*
   * testName: remoteAddByHelloEJBFromAssemblyBean
   * 
   * @assertion_ids:
   * 
   * @test_Strategy: hello ejb is packaged as a standalone ejb module and
   * deployed separately. It client view jar is packaged inside current ear and
   * referenced by both appclient and ejb jar thru MANIFEST.MF appclient ->
   * assemblyBean -> helloBean
   */
  public void remoteAddByHelloEJBFromAssemblyBean() throws Exception {
    String result = remoteAssemblyBean.callHelloBean();
    if (result != null) {
      TLogger.log("Got expected result: " + result);
    } else {
      throw new Exception(
          "Expecting a non-null result from remoteAssemblyBean.callHelloBean(), but got null.");
    }
  }
starksm64 commented 1 month ago

@scottmarlow see the standalone JavaTestNameVisitor class I'm using in the javafx app to parse the test method names. This is a standalone usage of the JavaParser from openrewrite without any rewrite rules usage to simply gather the method names from the class.

I figured out how to get the references to superclass methods that are not overriden by looking at the block end comments. See the visitBlock(J.Block block, ExecutionContext executionContext) method. This does not go to the superclass method to try to get the correct throws type. It just assumes Exception for now.

scottmarlow commented 1 month ago

Just as an fyi.

https://github.com/jakartaee/platform-tck/blob/main/ejb30/src/main/java/com/sun/ts/tests/ejb30/assembly/appres/appclientejb/Client.java#L125 is an example of two tests that do not throw an exception and for that reason, I will allow the case of zero exceptions (currently I throw an exception if there are zero exceptions or more than one exceptions being thrown).

If we hit any cases of tests throwing more than one exception, we can retool for that by not failing and also update TestMethodInfo to allow multiple exceptions to be thrown.

scottmarlow commented 1 month ago

https://github.com/jakartaee/platform-tck/blob/main/ejb30/src/main/java/com/sun/ts/tests/ejb30/bb/async/common/annotated/AnnotatedClientBase.java#L153 is a test method that does have two exceptions in the throws clause.

scottmarlow commented 1 month ago

If there are going to be a non-trivial number of custom exceptions on test methods, we will need to update the api to take the method name and exception type to throw, e.g., something like

Should we close this issue and open a new one for allowing multiple exceptions in the throws clause like https://github.com/jakartaee/platform-tck/blob/main/ejb30/src/main/java/com/sun/ts/tests/ejb30/bb/async/common/annotated/AnnotatedClientBase.java#L153?

starksm64 commented 1 month ago

I think this issue can be closed as complete. You can already just passing multiple exceptions to the throwsException string as that is just output as is with a "throws " in front of it. Here is an example of two exceptions that works:

    @Test
    public void testejb32_lite_timer_basic_concurrency() throws IOException {
        TestPackageInfoBuilder builder = new TestPackageInfoBuilder(tsHome);
        List<TestMethodInfo> testMethods = Arrays.asList(
                new TestMethodInfo("lookupTimerService", "InterruptedException, java.util.concurrent.ExecutionException"),
                new TestMethodInfo("writeLockTimeout", "")
        );
        Class<?> baseTestClass = com.sun.ts.tests.ejb32.lite.timer.basic.concurrency.Client.class;
        TestPackageInfo packageInfo = builder.buildTestPackgeInfoEx(baseTestClass, testMethods);
        System.out.println(packageInfo);
        System.out.println(packageInfo.getTestClientFiles());
    }