@Override
    public void run() {
        try { // make sure we call afterRun() even on crashes
            // and operate countdown latches, else we may hang the parallel runner
            if (steps == null) {
                beforeRun();
            }
            if (skipped) {
                return;
            }
            int count = steps.size();
            int index = 0;
            while ((index = nextStepIndex()) < count) {
                currentStep = steps.get(index);
                execute(currentStep);
                if (currentStepResult != null) { // can be null if debug step-back or hook skip
                    result.addStepResult(currentStepResult);
                }
            }
        } catch (Exception e) {
            if (currentStepResult != null) {
                result.addStepResult(currentStepResult);
            }
            logError("scenario [run] failed\n" + StringUtils.throwableToString(e));
            currentStepResult = result.addFakeStepResult("scenario [run] failed", e);
        } finally {
            if (!skipped) {
                afterRun();
                if (isFailed() && engine.getConfig().isAbortSuiteOnFailure()) {
                    featureRuntime.suite.abort();
                }
            }
            if (caller.isNone()) {
                logAppender.close(); // reclaim memory
            }
        }
    }
@Test
    void testGetSetAndRemove() {
        run(
                "karate.set('foo', 1)",
                "karate.set('bar', { hello: 'world' })",
                "karate.set({ a: 2, b: 'hey' })",
                "karate.setXml('fooXml', '<foo>bar</foo>')",
                "copy baz = bar",
                "karate.set('baz', '$.a', 1)",
                "karate.remove('baz', 'hello')",
                "copy bax = fooXml",
                "karate.setXml('bax', '/foo', '<a>1</a>')",
                "def getFoo = karate.get('foo')",
                "def getNull = karate.get('blah')",
                "def getDefault = karate.get('blah', 'foo')",
                "def getPath = karate.get('bar.hello')"
        );
        assertEquals(get("foo"), 1);
        assertEquals(get("a"), 2);
        assertEquals(get("b"), "hey");
        matchVar("bar", "{ hello: 'world' }");
        Object fooXml = get("fooXml");
        assertTrue(Match.that(fooXml).isXml());
        matchVar("fooXml", "<foo>bar</foo>");
        matchVar("baz", "{ a: 1 }");
        Match.that(get("bax")).isEqualTo("<foo><a>1</a></foo>");
        assertEquals(get("getFoo"), 1);
        assertEquals(get("getNull"), null);
        assertEquals(get("getDefault"), "foo");
        assertEquals(get("getPath"), "world");
    }