All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.centurylink.mdw.services.test.TestCaseScript Maven / Gradle / Ivy

There is a newer version: 6.1.39
Show newest version
/*
 * Copyright (C) 2017 CenturyLink, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.centurylink.mdw.services.test;

import com.centurylink.mdw.activity.types.AdapterActivity;
import com.centurylink.mdw.common.service.ServiceException;
import com.centurylink.mdw.constant.OwnerType;
import com.centurylink.mdw.model.asset.Asset;
import com.centurylink.mdw.model.asset.api.AssetInfo;
import com.centurylink.mdw.model.workflow.ActivityRuntimeContext;
import com.centurylink.mdw.model.workflow.Process;
import com.centurylink.mdw.model.workflow.ProcessInstance;
import com.centurylink.mdw.services.ServiceLocator;
import com.centurylink.mdw.test.*;
import com.centurylink.mdw.test.TestCase.Status;
import com.centurylink.mdw.xml.DomHelper;
import com.centurylink.mdw.xml.XmlPath;
import groovy.json.JsonSlurper;
import groovy.lang.Binding;
import groovy.lang.Closure;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import groovy.util.DelegatingScript;
import groovy.util.XmlSlurper;
import groovy.util.slurpersupport.GPathResult;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public abstract class TestCaseScript extends Script {

    public boolean isOnServer() { return true; }  // always true for server-run testing

    // values for placeholder access
    public String getMasterRequestId() {
        return getTestCaseRun().getMasterRequestId();
    }
    public void setMasterRequestId(String masterRequestId) {
        getTestCaseRun().setMasterRequestId(masterRequestId);
    }
    /**
     * In case it's assigned through binding.
     */
    protected void syncMasterRequestId() {
        if (getBinding().hasVariable("masterRequestId")) {
            Object defined = getBinding().getVariable("masterRequestId");
            TestCaseRun run = getTestCaseRun();
            if (!run.getMasterRequestId().equals(defined)) {
                String old = run.getMasterRequestId();
                run.setMasterRequestId(String.valueOf(defined));
                if (run.getMasterRequestListener() != null)
                    run.getMasterRequestListener().syncMasterRequestId(old, run.getMasterRequestId());
                if (run.isVerbose())
                  run.getLog().println("masterRequestId: " + getMasterRequestId());
            }
        }
    }

    // server-side placeholders: simply return server-side syntax for replacement on the server
    public String getProcessInstanceId() { return "{$ProcessInstanceId}"; }
    public String getActivityInstanceId() { return "{$ActivityInstanceId}"; }
    // TODO public Map getVariables()

    private TestCaseProcess process; // current top level process
    public TestCaseProcess getProcess() {
        return process;
    }
    private TestCaseResponse response;
    public TestCaseResponse getResponse() {
        return response;
    }

    public String getResponseMessage() {
        return response == null ? null : response.getActual();
    }

    public List getProcessInstances() {
        return getTestCaseRun().getProcessInstances();
    }
    public ProcessInstance getMasterProcessInstance() {
        List instances = getProcessInstances();
        if (instances != null) {
            for (ProcessInstance instance : instances) {
                if (!OwnerType.PROCESS_INSTANCE.equals(instance.getOwner()))
                    return instance;
            }
        }
        return null;
    }

    // no-op methods for keywords
    public TestCaseProcess process() { return process; }
    public TestCaseResponse response() { return response; }

    private ApiRequest apiRequest; // current api test
    public ApiRequest request(String target) throws TestException {
        return request(target, null);
    }

    public ApiRequest request(String target, Closure cl) throws TestException {
        return request(target, null, cl);
    }

    public ApiRequest request(String target, Map options, Closure cl) throws TestException {
        int dotPostmanSlash = target.lastIndexOf(".postman/");
        if (dotPostmanSlash == -1)
            throw new TestException("Bad API test path: " + target);
        String assetPath = target.substring(0, dotPostmanSlash + 8);
        Asset asset = asset(assetPath);
        if (asset == null)
            throw new TestException("API test case asset not found: " + assetPath);
        TestCase apiTestCase = new TestCase(asset.getPackageName(), new AssetInfo(asset.getName()));
        try {
            String itemPath = asset.getPackageName() + "/" + asset.getName() + "/"
                    + target.substring(dotPostmanSlash + 9).replace('/', '~');
            TestCaseItem item = ServiceLocator.getTestingServices().getTestCaseItem(itemPath);
            if (item == null)
                throw new TestException("Test case item not found: " + itemPath);
            apiTestCase.addItem(item);
            apiRequest = new ApiRequest(apiTestCase, options);
            if (cl != null) {
                cl.setResolveStrategy(Closure.DELEGATE_FIRST);
                cl.setDelegate(apiRequest);
                cl.call();
            }

            return apiRequest;
        }
        catch (ServiceException ex) {
            throw new TestException(ex.getMessage(), ex);
        }
    }

    public ApiResponse submit(ApiRequest apiRequest) throws TestException {
        TestCase apiTestCase = apiRequest.getTestCase();
        TestCaseItem testItem = apiRequest.getTestCase().getItems().get(0); // TODO
        if (apiRequest.getOptions() != null)
            testItem.setOptions(new JSONObject(apiRequest.getOptions()));
        if (testItem.getOption("caseName") == null)
            testItem.setOption("caseName", getTestCase().getAsset().getRootName());
        if (testItem.getOption("retainLog") == null)
            testItem.setOption("retainLog", "true");
        if (testItem.getOption("retainResult") == null)
            testItem.setOption("retainResult", "true");
        testItem.setOption("debug", String.valueOf(getTestCaseRun().isVerbose()));
        if (apiRequest.getValues() != null)
            testItem.setValues(new JSONObject(apiRequest.getValues()));
        JSONObject itemResponse = getTestCaseRun().submitItem(apiTestCase, testItem);
        if (itemResponse == null)
            return new ApiResponse(new JSONObject());
        else
            return new ApiResponse(testItem.getResponse());
    }

    public TestCaseProcess start(String target) throws TestException {
        return start(process(target));
    }

    public TestCaseProcess start(TestCaseProcess process) throws TestException {
        syncMasterRequestId();
        if (getTestCaseRun().isLoadTest()) {
            send(new TestCaseMessage(getMasterRequestId(), process));
            return null;
        }

        getTestCaseRun().startProcess(process);
        return process;
    }

    public TestCaseProcess process(String target) throws TestException {
        return process(target, null);
    }

    public TestCaseProcess process(String target, Closure cl) throws TestException {
        process = new TestCaseProcess(getTestCaseRun().getProcess(target));
        if (cl != null) {
            cl.setResolveStrategy(Closure.DELEGATE_FIRST);
            cl.setDelegate(process);
            cl.call();
        }
        if (getTestCaseRun().testCaseProcess == null)
            getTestCaseRun().testCaseProcess = process;
        return process;
    }

    public TestCaseProcess process(Closure cl) throws TestException {
        cl.setResolveStrategy(Closure.DELEGATE_FIRST);
        cl.setDelegate(process);
        cl.call();
        if (getTestCaseRun().testCaseProcess == null)
            getTestCaseRun().testCaseProcess = process;
        return process;
    }

    public TestCaseProcess[] processes(String... targets) throws TestException {
        List processes = new ArrayList<>();
        for (int i = 0; i < targets.length; i++) {
            try {
                Process process = getTestCaseRun().getProcess(targets[i]);
                processes.add(new TestCaseProcess(process));
            }
            catch (TestException ex) {
                getTestCaseRun().getLog().println("Failed to load process " + targets[i]);
                if (i == 0)  // by convention > 0 are subprocesses where exception is expected
                    throw ex;
            }
        }
        return processes.toArray(new TestCaseProcess[0]);
    }

    public Verifiable verify(Object object) throws TestException {
        if (object instanceof TestCaseProcess[])
            return verify((TestCaseProcess[])object, null);
        if (object instanceof TestCaseProcess)
            return verify(new TestCaseProcess[]{(TestCaseProcess)object}, null);
        else if (object instanceof TestCaseResponse)
            return verify((TestCaseResponse)object);
        else if (object instanceof ApiResponse)
            return verify((ApiResponse)object);
        else if (object instanceof File) {
            try {
                response.setExpected(new String(getTestCaseRun().read((File)object)));
                return verify(response);
            }
            catch (IOException ex) {
                throw new TestException(ex.getMessage(), ex);
            }
        }
        else if (object instanceof String) {
            response.setExpected((String)object);
            return verify(response);
        }
        else
            throw new TestException("Unsupported verification object: " + object);
    }

    public List load(TestCaseProcess process) throws TestException {
        return load(new TestCaseProcess[]{process});
    }

    public List load(TestCaseProcess[] processes) throws TestException {
        Asset expectedResults = process.getExpectedResults();
        if (expectedResults == null)
            expectedResults = getDefaultExpectedResults();
        return getTestCaseRun().loadProcess(processes, expectedResults);
    }

    public Verifiable verify(ApiResponse response) throws TestException {
        return verify(response, null);
    }

    public Verifiable verify(ApiResponse response, Closure cl) throws TestException {

        if (cl != null) {
            cl.setResolveStrategy(Closure.DELEGATE_FIRST);
            cl.setDelegate(response);
            cl.call();
        }

        try {
            TestCase testCase = getTestCaseRun().getTestCase();
            TestCaseItem item = new TestCaseItem(testCase.getName());
            if (response.getOptions() != null)
                item.setOptions(new JSONObject(response.getOptions()));
            if (item.getOption("caseName") == null)
                item.setOption("caseName", getTestCase().getAsset().getRootName());
            if (item.getOption("retainLog") == null)
                item.setOption("retainLog", "true");
            if (item.getOption("retainResult") == null)
                item.setOption("retainResult", "true");
            item.setOption("verify", "true");
            if (response.getValues() != null)
                item.setValues(new JSONObject(response.getValues()));
            item.setStatus(Status.Stopped); // otherwise this adhoc item causes havoc
            testCase.addItem(item);
            getTestCaseRun().verifyItem(testCase, item);
            return response;
        }
        catch (Exception ex) {
            throw new TestException(ex.getMessage(), ex);
        }
    }

    public Verifiable verify(TestCaseProcess process, Closure cl) throws TestException {
        return verify(new TestCaseProcess[]{process}, cl);
    }

    public Verifiable verify(TestCaseProcess[] processes, Closure cl) throws TestException {
        getTestCaseRun().setPreFilter(before -> substitute(before));

        if (cl != null) {
            cl.setResolveStrategy(Closure.DELEGATE_FIRST);
            cl.setDelegate(process);
            cl.call();
        }
        if (process.getExpectedResults() == null)
            process.setExpectedResults(getDefaultExpectedResults());
        if (process.getExcludeVariables() != null && !process.getExcludeVariables().isEmpty())
            processes[0].setExcludeVariables(process.getExcludeVariables());

        process.setSuccess(getTestCaseRun().verifyProcess(processes, process.getExpectedResults()));
        return process;
    }

    /**
     * Default naming convention for expected results asset (need not exist).
     */
    public Asset getDefaultExpectedResults() throws TestException {
        String testAssetName = getTestCaseRun().getTestCase().getName();
        String resultsAssetName = testAssetName.substring(0, testAssetName.lastIndexOf('.')) + ".yaml";
        if (getTestCaseRun().isCreateReplace()) {
            // asset will be created
            String testAssetFile = getTestCaseRun().getTestCase().getAsset().getFile().toString();
            File file = new File(testAssetFile.substring(0, testAssetFile.lastIndexOf('.')) + ".yaml");
            Asset expectedResults = new Asset(getTestCaseRun().getTestCase().getPackage(), file.getName(), 1, file);
            expectedResults.setFile(file);
            return expectedResults;
        }
        else {
            return asset(resultsAssetName);
        }
    }

    public TestCaseResponse send(String payload) throws TestException {
        syncMasterRequestId();
        return send(message(payload));
    }

    public TestCaseResponse send(File file) throws TestException {
        try {
            syncMasterRequestId();
            return send(message(new String(getTestCaseRun().read(file))));
        }
        catch (IOException ex) {
            throw new TestException(ex.getMessage(), ex);
        }
    }

    public TestCaseResponse send(Asset asset) throws TestException {
        syncMasterRequestId();
        return send(message(asset.getText()));
    }

    public TestCaseResponse send(TestCaseMessage message) throws TestException {
        message.setPayload(substitute(message.getPayload()));
        response = getTestCaseRun().sendMessage(message);
        return response;
    }

    public TestCaseResponse get(TestCaseHttp http) throws TestException {
        http.setMethod("get");
        response = getTestCaseRun().http(http);
        return response;
    }

    public TestCaseResponse post(TestCaseHttp http) throws TestException {
        http.setMethod("post");
        response = getTestCaseRun().http(http);
        return response;
    }

    public TestCaseResponse put(TestCaseHttp http) throws TestException {
        http.setMethod("put");
        response = getTestCaseRun().http(http);
        return response;
    }

    public TestCaseResponse patch(TestCaseHttp http) throws TestException {
        http.setMethod("patch");
        response = getTestCaseRun().http(http);
        return response;
    }

    public TestCaseResponse delete(TestCaseHttp http) throws TestException {
        http.setMethod("delete");
        response = getTestCaseRun().http(http);
        return response;
    }

    public TestCaseHttp http(String uri) {
        return http(uri, null);
    }

    public TestCaseHttp http(String uri, Closure cl) {
        syncMasterRequestId();
        TestCaseHttp http = new TestCaseHttp(uri);
        if (cl != null) {
            TestCaseMessage message = new TestCaseMessage();
            cl.setResolveStrategy(Closure.DELEGATE_FIRST);
            cl.setDelegate(message);
            cl.call();
            if (message.getPayload() != null)
                message.setPayload(substitute(message.getPayload()));
            http.setMessage(message);
        }
        return http;
    }

    public TestCaseResponse response(Closure cl) throws TestException {
        if (response == null)
            response = new TestCaseResponse();
        if (cl != null) {
            cl.setResolveStrategy(Closure.DELEGATE_FIRST);
            cl.setDelegate(response);
            cl.call();
        }
        return response;
    }

    public Verifiable verify(TestCaseResponse response) throws TestException {
        if (!getTestCaseRun().isLoadTest()) {
            this.response = response;
            response.setExpected(substitute(response.getExpected()));
            response.setSuccess(getTestCaseRun().verifyResponse(response));
        }
        return response;
    }

    public Verifiable verifyXml(TestCaseResponse response) throws TestException {
        if (!getTestCaseRun().isLoadTest()) {
            this.response = response;
            try {
                response.setActual(DomHelper.toXml(DomHelper.toDomDocument(response.getActual())));
                response.setExpected(DomHelper.toXml(DomHelper.toDomDocument(substitute(response.getExpected()))));
                response.setSuccess(getTestCaseRun().verifyResponse(response));
            }
            catch (Exception ex) {
                throw new TestException(ex.getMessage(), ex);
            }
        }
        return response;
    }

    public TestCaseMessage message(String payload) throws TestException {
        TestCaseMessage message = new TestCaseMessage();
        message.setPayload(substitute(payload));
        return message;
    }

    public TestCaseMessage message(Closure cl) throws TestException {
        return message(null, cl);
    }

    public TestCaseMessage message(String protocol, Closure cl) throws TestException {
        TestCaseMessage message = protocol == null ? new TestCaseMessage() : new TestCaseMessage(protocol);
        if (cl != null) {
            cl.setResolveStrategy(Closure.DELEGATE_FIRST);
            cl.setDelegate(message);
            cl.call();
        }
        return message;
    }

    public TestCaseTask action(TestCaseTask task) throws TestException {
        getTestCaseRun().performTaskAction(task);
        return task;
    }

    public TestCaseTask task(String name, Closure cl) {
        TestCaseTask tcTask = new TestCaseTask(name);
        if (cl != null) {
            cl.setResolveStrategy(Closure.DELEGATE_FIRST);
            cl.setDelegate(tcTask);
            cl.call();
        }
        return tcTask;
    }

    public TestCaseEvent notify(TestCaseEvent event) throws TestException {
        getTestCaseRun().notifyEvent(event);
        return event;
    }

    public TestCaseEvent event(String eventId) throws TestException {
        return event(eventId, null);
    }

    public TestCaseEvent event(String eventId, Closure cl) throws TestException {
        TestCaseEvent event = new TestCaseEvent(eventId);
        if (cl != null) {
            cl.setResolveStrategy(Closure.DELEGATE_FIRST);
            cl.setDelegate(event);
            cl.call();
        }
        return event;
    }

    public TestCaseAdapterStub stub(TestCaseAdapterStub adapterStub) throws TestException {
        syncMasterRequestId();
        getTestCaseRun().addAdapterStub(adapterStub);
        return adapterStub;
    }

    public TestCaseAdapterStub endpoint(Closure matcher, Closure init) throws TestException {
        return endpoint(matcher, null, init);
    }

    public TestCaseAdapterStub endpoint(Closure matcher, Closure responder, Closure init) throws TestException {
        TestCaseAdapterStub adapterStub = adapter(matcher, responder, init);
        adapterStub.setEndpoint(true);
        return adapterStub;
    }

    public TestCaseAdapterStub adapter(Closure matcher, Closure init) throws TestException {
        return adapter(matcher, null, init);
    }

    /**
     * responder closure call is delayed until stub server calls back
     */
    public TestCaseAdapterStub adapter(Closure matcher, Closure responder, Closure init) throws TestException {
        final TestCaseAdapterStub adapterStub = new TestCaseAdapterStub(matcher, responder);
        if (init != null) {
            init.setResolveStrategy(Closure.DELEGATE_FIRST);
            init.setDelegate(adapterStub);
            init.call();
        }
        if (responder == null) {
            adapterStub.setResponder(new Closure(this, adapterStub) {
                @Override
                public String call(Object request) {
                    // binding for request
                    final TestCaseRun testCaseRun = getTestCaseRun();
                    if (adapterStub.getResponse().contains("${")) {
                        try {
                            Binding binding = getBinding();
                            if (request.toString().startsWith("{")) {
                                Object req = new JsonSlurper().parseText(request.toString());
                                binding.setVariable("request", req);
                            }
                            else if (request.toString().length() > 0){
                                GPathResult gpathRequest = new XmlSlurper().parseText(request.toString());
                                binding.setVariable("request", gpathRequest);
                            }
                            CompilerConfiguration compilerCfg = new CompilerConfiguration();
                            compilerCfg.setScriptBaseClass(DelegatingScript.class.getName());
                            GroovyShell shell = new GroovyShell(TestCaseScript.class.getClassLoader(), binding, compilerCfg);
                            shell.setProperty("out", testCaseRun.getLog());
                            DelegatingScript script = (DelegatingScript) shell.parse("return \"\"\"" + adapterStub.getResponse() + "\"\"\"");
                            script.setDelegate(TestCaseScript.this);
                            return script.run().toString();
                        }
                        catch (Exception ex) {
                            getTestCaseRun().getLog().println("Cannot perform stub response substitutions for request: " + request);
                            ex.printStackTrace(getTestCaseRun().getLog());
                        }
                    }
                    return adapterStub.getResponse();
                }
            });
        }
        return adapterStub;
    }

    public TestCaseActivityStub activity(Closure matcher, Closure completer) throws TestException {
        return new TestCaseActivityStub(matcher, completer);
    }

    public TestCaseActivityStub activity(final String match, Closure completer) throws TestException {
        return new TestCaseActivityStub(new Closure(this, this) {
            @Override
            public Boolean call(Object context) {
                ActivityRuntimeContext runtimeContext = (ActivityRuntimeContext) context;
                String matchProcess = process.getProcess().getName();
                String matchActivity = match;
                int colon = match.lastIndexOf(':');
                if (colon > 0) {
                    matchActivity = match.substring(colon + 1);
                    int slash = match.lastIndexOf('/');
                    if (slash > 0) {
                        matchProcess = match.substring(slash + 1, colon);
                    }
                    else {
                        matchProcess = match.substring(0, colon);
                    }
                }

                return runtimeContext.getProcess().getName().equals(matchProcess) &&
                        (runtimeContext.getActivity().getName().equals(matchActivity) ||
                            runtimeContext.getActivityLogicalId().equals(matchActivity));
            }
        }, completer);
    }

    /**
     * Matches according to MDW XPath.
     */
    public Closure xpath(final String condition) throws TestException {
        return new Closure(this, this) {
            @Override
            public Boolean call(Object request) {
                try {
                    XmlPath xpath = new XmlPath(condition);
                    String v = xpath.evaluate(XmlObject.Factory.parse(request.toString()));
                    return v != null;
                }
                catch (XmlException ex) {
                    ex.printStackTrace(getTestCaseRun().getLog());
                    getTestCaseRun().getLog().println("Failed to parse request as XML. Stub response: " + AdapterActivity.MAKE_ACTUAL_CALL);
                    return false;
                }
            }
        };
    }

    /**
     * Matches according to GPath.
     */
    public Closure gpath(final String condition) throws TestException {
        return new Closure(this, this) {
            @Override
            public Boolean call(Object request) {
                try {
                    GPathResult gpathRequest = new XmlSlurper().parseText(request.toString());
                    Binding binding = getBinding();
                    binding.setVariable("request", gpathRequest);
                    return (Boolean) new GroovyShell(binding).evaluate(condition);
                }
                catch (Exception ex) {
                    ex.printStackTrace(getTestCaseRun().getLog());
                    getTestCaseRun().getLog().println("Failed to parse request as XML/JSON. Stub response: " + AdapterActivity.MAKE_ACTUAL_CALL);
                    return false;
                }
            }
        };
    }

    public void sleep(int seconds) {
        getTestCaseRun().sleep(seconds);
    }

    public void wait(Object object) throws TestException {
        if (object instanceof TestCaseProcess)
            wait((TestCaseProcess)object);
        else
            throw new TestException("Unsupported wait object: " + object);
    }

    public void wait(TestCaseProcess process) throws TestException {
        getTestCaseRun().wait(process);
    }

    @Deprecated
    public File file(String name) throws TestException {
        return asset(name).getFile();
    }

    public Asset asset(String path) throws TestException {
        return getTestCaseRun().getAsset(path);
    }

    protected TestCaseRun getTestCaseRun() {
        return (TestCaseRun) getBinding().getVariable("testCaseRun");
    }

    protected TestCase getTestCase() {
        return getTestCaseRun().getTestCase();
    }

    /**
     * performs groovy substitutions with this as delegate and inherited bindings
     */
    protected String substitute(String before) {
        if (!before.contains("${"))
            return before;
        // escape all $ not followed by curly braces on same line
        before = before.replaceAll("\\$(?!\\{)", "\\\\\\$");
        // escape all regex -> ${~
        before = before.replaceAll("\\$\\{~", "\\\\\\$\\{~");
        // escape all escaped newlines
        before = before.replaceAll("\\\\n", "\\\\\\\\\\n");
        before = before.replaceAll("\\\\r", "\\\\\\\\\\r");
        // escape all escaped quotes
        before = before.replaceAll("\\\"", "\\\\\"");

        CompilerConfiguration compilerCfg = new CompilerConfiguration();
        compilerCfg.setScriptBaseClass(DelegatingScript.class.getName());

        // Groovy has limit on size of script so split/re-join if needed
        int index = 1;
        int initialFromIdx = 50000;
        int maxGroovyScriptLength = 65000;  //it is 65536 but allowing a bit of slack for maneuvering
        String remaining = before;
        List specialChars = Arrays.asList('$','{','}','\\','"','n','r');
        StringBuilder after = new StringBuilder();
        while (index > 0) {
             String chunk;
             index = remaining.indexOf("variable:", initialFromIdx);
             int fromIdx = initialFromIdx;
             while (index > maxGroovyScriptLength && (fromIdx/10) > 5) {
                 fromIdx = fromIdx/10;
                 index = remaining.indexOf("variable:", fromIdx);
             }
             if (index > 0) {
                 if (index > maxGroovyScriptLength) { // Single variable value is longer than groovy max chars
                     index = maxGroovyScriptLength;  // Start with this chunk
                     String tmp = remaining.substring(0, index+1); //In case last char is $ so include full ${
                     // Check for ending inside an expression or special character
                     while (tmp.lastIndexOf("${") >= 0 && tmp.lastIndexOf("${") < index ||
                             specialChars.contains(tmp.charAt(index-1))) {
                         // If inside an expression, move index outside of it ${...}
                         if (remaining.indexOf("}", tmp.lastIndexOf("${")) > (index+1))
                             index = remaining.indexOf("}", tmp.lastIndexOf("${")) + 1;
                         // Make sure not ending on a special character
                         while (specialChars.contains(remaining.charAt(index-1)))
                             index++; //Special character, move forward until regular character
                         tmp = remaining.substring(0, index+1); // Check if now inside another expressions
                     }
                 }
                 chunk = remaining.substring(0, index);
                 remaining = remaining.substring(index);
             }
             else {
                 chunk = remaining;
             }
             GroovyShell shell = new GroovyShell(TestCaseScript.class.getClassLoader(), getBinding(), compilerCfg);
             DelegatingScript script = (DelegatingScript) shell.parse("return \"\"\"" + chunk + "\"\"\"");
             script.setDelegate(TestCaseScript.this);
             // restore escaped \$ to $ for comparison
             after.append(script.run().toString().replaceAll("\\\\$", "\\$"));
        }
        return after.toString();
    }

    public boolean isStubbing() {
        return getTestCaseRun().isStubbing();
    }

    public boolean isHasTestingPackage() throws TestException {
        return asset("com.centurylink.mdw.testing/readme.md").getFile().exists();
    }

    public void logLine(String message) {
        getTestCaseRun().getLog().println(message);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy