Search in sources :

Example 1 with TestScriptSpecification

use of runner.config.TestScriptSpecification in project jade-data-repo by DataBiosphere.

the class TestRunner method executeTestConfiguration.

void executeTestConfiguration() throws Exception {
    // specify any value overrides in the Helm chart, then deploy
    if (!config.server.skipDeployment) {
    // modifyHelmValuesAndDeploy();
    }
    // update any Kubernetes properties specified by the test configuration
    if (!config.server.skipKubernetes) {
        KubernetesClientUtils.buildKubernetesClientObject(config.server);
        modifyKubernetesPostDeployment();
    }
    // get an instance of the API client per test user
    for (TestUserSpecification testUser : config.testUsers) {
        ApiClient apiClient = new ApiClient();
        apiClient.setBasePath(config.server.uri);
        GoogleCredentials userCredential = AuthenticationUtils.getDelegatedUserCredential(testUser);
        AccessToken userAccessToken = AuthenticationUtils.getAccessToken(userCredential);
        apiClient.setAccessToken(userAccessToken.getTokenValue());
        apiClientsForUsers.put(testUser.name, apiClient);
    }
    // get an instance of each test script class
    for (TestScriptSpecification testScriptSpecification : config.testScripts) {
        try {
            TestScript testScriptInstance = testScriptSpecification.scriptClass.newInstance();
            // set the billing account for the test script to use
            testScriptInstance.setBillingAccount(config.billingAccount);
            // set any parameters specified by the configuration
            testScriptInstance.setParameters(testScriptSpecification.parameters);
            scripts.add(testScriptInstance);
        } catch (IllegalAccessException | InstantiationException niEx) {
            throw new IllegalArgumentException("Error calling constructor of TestScript class: " + testScriptSpecification.scriptClass.getName(), niEx);
        }
    }
    // call the setup method of each test script
    Exception setupExceptionThrown = callTestScriptSetups();
    if (setupExceptionThrown != null) {
        // ignore any exceptions thrown by cleanup methods
        callTestScriptCleanups();
        throw new RuntimeException("Error calling test script setup methods.", setupExceptionThrown);
    }
    // for each test script
    List<ApiClient> apiClientList = new ArrayList<>(apiClientsForUsers.values());
    for (int tsCtr = 0; tsCtr < scripts.size(); tsCtr++) {
        TestScript testScript = scripts.get(tsCtr);
        TestScriptSpecification testScriptSpecification = config.testScripts.get(tsCtr);
        // add a description to the user journey threads/results that includes any parameters
        String userJourneyDescription = testScriptSpecification.name;
        if (testScriptSpecification.parameters != null) {
            userJourneyDescription += ": " + String.join(",", testScriptSpecification.parameters);
        }
        // create a thread pool for running its user journeys
        ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(testScriptSpecification.numberToRunInParallel);
        threadPools.add(threadPool);
        // kick off the user journey(s), one per thread
        List<UserJourneyThread> userJourneyThreads = new ArrayList<>();
        for (int ujCtr = 0; ujCtr < testScriptSpecification.totalNumberToRun; ujCtr++) {
            ApiClient apiClient = apiClientList.get(ujCtr % apiClientList.size());
            userJourneyThreads.add(new UserJourneyThread(testScript, userJourneyDescription, apiClient));
        }
        // TODO: support different patterns of kicking off user journeys. here they're all queued at
        // once
        List<Future<UserJourneyResult>> userJourneyFutures = threadPool.invokeAll(userJourneyThreads);
        userJourneyFutureLists.add(userJourneyFutures);
    }
    // wait until all threads either finish or time out
    for (int ctr = 0; ctr < scripts.size(); ctr++) {
        TestScriptSpecification testScriptSpecification = config.testScripts.get(ctr);
        ThreadPoolExecutor threadPool = threadPools.get(ctr);
        threadPool.shutdown();
        long totalTerminationTime = testScriptSpecification.expectedTimeForEach * testScriptSpecification.totalNumberToRun;
        boolean terminatedByItself = threadPool.awaitTermination(totalTerminationTime, testScriptSpecification.expectedTimeForEachUnitObj);
        // if the threads didn't finish in the expected time, then send them interrupts
        if (!terminatedByItself) {
            threadPool.shutdownNow();
        }
        if (!threadPool.awaitTermination(secondsToWaitForPoolShutdown, TimeUnit.SECONDS)) {
            System.out.println("Thread pool for test script " + ctr + " (" + testScriptSpecification.name + ") failed to terminate.");
        }
    }
    // compile the results from all thread pools
    for (int ctr = 0; ctr < scripts.size(); ctr++) {
        List<Future<UserJourneyResult>> userJourneyFutureList = userJourneyFutureLists.get(ctr);
        TestScriptSpecification testScriptSpecification = config.testScripts.get(ctr);
        for (Future<UserJourneyResult> userJourneyFuture : userJourneyFutureList) {
            UserJourneyResult result = null;
            if (userJourneyFuture.isDone())
                try {
                    // user journey thread completed and populated its own return object, which may include
                    // an exception
                    result = userJourneyFuture.get();
                    result.completed = true;
                } catch (ExecutionException execEx) {
                    // user journey thread threw an exception and didn't populate its own return object
                    result = new UserJourneyResult(testScriptSpecification.name, "");
                    result.completed = false;
                    result.exceptionThrown = execEx;
                }
            else {
                // user journey either was never started or got cancelled before it finished
                result = new UserJourneyResult(testScriptSpecification.name, "");
                result.completed = false;
            }
            userJourneyResults.add(result);
        }
    }
    // call the cleanup method of each test script
    Exception cleanupExceptionThrown = callTestScriptCleanups();
    if (cleanupExceptionThrown != null) {
        throw new RuntimeException("Error calling test script cleanup methods.", cleanupExceptionThrown);
    }
    // delete the deployment and restore any Kubernetes settings
    if (!config.server.skipDeployment) {
        deleteDeployment();
    }
    if (!config.server.skipKubernetes) {
        restoreKubernetesSettings();
    }
    // cleanup data project
    cleanupLeftoverTestData();
}
Also used : ArrayList(java.util.ArrayList) AccessToken(com.google.auth.oauth2.AccessToken) GoogleCredentials(com.google.auth.oauth2.GoogleCredentials) TestScriptSpecification(runner.config.TestScriptSpecification) TestUserSpecification(runner.config.TestUserSpecification) ExecutionException(java.util.concurrent.ExecutionException) ApiClient(bio.terra.datarepo.client.ApiClient) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Future(java.util.concurrent.Future) ThreadPoolExecutor(java.util.concurrent.ThreadPoolExecutor)

Aggregations

ApiClient (bio.terra.datarepo.client.ApiClient)1 AccessToken (com.google.auth.oauth2.AccessToken)1 GoogleCredentials (com.google.auth.oauth2.GoogleCredentials)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 ExecutionException (java.util.concurrent.ExecutionException)1 Future (java.util.concurrent.Future)1 ThreadPoolExecutor (java.util.concurrent.ThreadPoolExecutor)1 TestScriptSpecification (runner.config.TestScriptSpecification)1 TestUserSpecification (runner.config.TestUserSpecification)1