You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2020/09/19 12:30:11 UTC

[tinkerpop] 01/01: TINKERPOP-2421 wip

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-2421
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 8bc173c3bbd48567c8f46a73bd8634b0f0dd10c4
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Sat Sep 19 08:29:03 2020 -0400

    TINKERPOP-2421 wip
---
 .../glv/GraphTraversalSource.template              | 22 ++++++-
 gremlin-javascript/glv/generate.groovy             |  1 +
 .../gremlin-javascript/lib/driver/client.js        |  8 +--
 .../gremlin-javascript/lib/driver/connection.js    | 23 ++++---
 .../lib/driver/driver-remote-connection.js         | 17 +++++-
 .../lib/process/graph-traversal.js                 | 32 ++++++----
 .../lib/process/traversal-strategy.js              | 70 +++++++---------------
 .../lib/structure/io/type-serializers.js           |  9 ++-
 .../test/integration/traversal-test.js             | 14 +++--
 .../gremlin-javascript/test/unit/traversal-test.js | 49 ++++-----------
 10 files changed, 129 insertions(+), 116 deletions(-)

diff --git a/gremlin-javascript/glv/GraphTraversalSource.template b/gremlin-javascript/glv/GraphTraversalSource.template
index fc55316..c5e490c 100644
--- a/gremlin-javascript/glv/GraphTraversalSource.template
+++ b/gremlin-javascript/glv/GraphTraversalSource.template
@@ -26,7 +26,7 @@ const { Traversal } = require('./traversal');
 const remote = require('../driver/remote-connection');
 const utils = require('../utils');
 const Bytecode = require('./bytecode');
-const { TraversalStrategies, VertexProgramStrategy } = require('./traversal-strategy');
+const { TraversalStrategies, VertexProgramStrategy, OptionsStrategy } = require('./traversal-strategy');
 
 
 /**
@@ -77,6 +77,26 @@ class GraphTraversalSource {
   }
 
   /**
+   * Graph Traversal Source with method.
+   * @param {String} key
+   * @param {Object} value if not specified, the value with default to {@code true}
+   * @returns {GraphTraversalSource}
+   */
+  with_(key, value=undefined) {
+    const val = value === undefined ? true : value;
+    let optionsStrategy = this.bytecode.sourceInstructions.find(
+        i => i[0] === "withStrategies" && i[1] instanceof OptionsStrategy);
+    if (optionsStrategy === undefined) {
+      optionsStrategy = new OptionsStrategy({[key]: val});
+      return this.withStrategies(optionsStrategy);
+    } else {
+      optionsStrategy[1].configuration[key] = val;
+      return new this.graphTraversalSourceClass(this.graph, new TraversalStrategies(this.traversalStrategies),
+          this.bytecode, this.graphTraversalSourceClass, this.graphTraversalClass);
+    }
+  }
+
+  /**
    * Returns the string representation of the GraphTraversalSource.
    * @returns {string}
    */
diff --git a/gremlin-javascript/glv/generate.groovy b/gremlin-javascript/glv/generate.groovy
index cd3e899..cfd1be5 100644
--- a/gremlin-javascript/glv/generate.groovy
+++ b/gremlin-javascript/glv/generate.groovy
@@ -87,6 +87,7 @@ def binding = ["enums": CoreImports.getClassImports()
                            !it.name.equals("clone") &&
                                    // Use hardcoded name to be for forward-compatibility
                                    !it.name.equals("withBindings") &&
+                                   !it.name.equals(TraversalSource.Symbols.with) &&
                                    !it.name.equals(TraversalSource.Symbols.withRemote) &&
                                    !it.name.equals(TraversalSource.Symbols.withComputer)
                        }.
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.js
index eaa9db1..e8d1baf 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/client.js
@@ -69,9 +69,10 @@ class Client {
    * Send a request to the Gremlin Server, can send a script or bytecode steps.
    * @param {Bytecode|string} message The bytecode or script to send
    * @param {Object} [bindings] The script bindings, if any.
+   * @param {Object} [requestOptions] Configuration specific to the current request.
    * @returns {Promise}
    */
-  submit(message, bindings) {
+  submit(message, bindings, requestOptions=undefined) {
     if (typeof message === 'string') {
       const args = {
         'gremlin': message,
@@ -83,12 +84,11 @@ class Client {
       if (this._options.session && this._options.processor === 'session') {
         args['session'] = this._options.session;
       }
-
-      return this._connection.submit(null, 'eval', args, null, this._options.processor || '');
+      return this._connection.submit(null, 'eval', Object.assign(args, requestOptions), null, this._options.processor || '');
     }
 
     if (message instanceof Bytecode) {
-      return this._connection.submit(message);
+      return this._connection.submit(message, 'bytecode', requestOptions);
     }
   }
 
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
index 67dce3a..28cb1d1 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/connection.js
@@ -156,16 +156,19 @@ class Connection extends EventEmitter {
 
   /** @override */
   submit(bytecode, op, args, requestId, processor) {
+    const requestIdDefined = (args !== undefined && args !== null && 'requestId' in args)
+    const rid = requestId === undefined || requestId === null ? (requestIdDefined ? args['requestId'] : utils.getUuid()) : requestId;
+    if (requestIdDefined) delete args['requestId'];
+
     return this.open().then(() => new Promise((resolve, reject) => {
-      if (requestId === null || requestId === undefined) {
-        requestId = utils.getUuid();
-        this._responseHandlers[requestId] = {
+      if (op !== 'authentication') {
+        this._responseHandlers[rid] = {
           callback: (err, result) => err ? reject(err) : resolve(result),
           result: null
         };
       }
 
-      const message = Buffer.from(this._header + JSON.stringify(this._getRequest(requestId, bytecode, op, args, processor)));
+      const message = Buffer.from(this._header + JSON.stringify(this._getRequest(rid, bytecode, op, args, processor)));
       this._ws.send(message);
     }));
   }
@@ -185,6 +188,13 @@ class Connection extends EventEmitter {
   _getRequest(id, bytecode, op, args, processor) {
     if (args) {
       args = this._adaptArgs(args, true);
+    } else {
+      args = {};
+    }
+
+    if (bytecode) {
+      args['gremlin'] = this._writer.adaptObject(bytecode);
+      args['aliases'] = { 'g': this.traversalSource }
     }
 
     return ({
@@ -192,10 +202,7 @@ class Connection extends EventEmitter {
       'op': op || 'bytecode',
       // if using op eval need to ensure processor stays unset if caller didn't set it.
       'processor': (!processor && op !== 'eval') ? 'traversal' : processor,
-      'args': args || {
-        'gremlin': this._writer.adaptObject(bytecode),
-        'aliases': { 'g': this.traversalSource }
-      }
+      'args': args
     });
   }
 
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.js
index 1632fda..62cbdb5 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/driver/driver-remote-connection.js
@@ -26,6 +26,7 @@ const rcModule = require('./remote-connection');
 const RemoteConnection = rcModule.RemoteConnection;
 const RemoteTraversal = rcModule.RemoteTraversal;
 const Client = require('./client');
+const OptionsStrategy = require('../process/traversal-strategy').OptionsStrategy;
 
 /**
  * Represents the default {@link RemoteConnection} implementation.
@@ -60,7 +61,21 @@ class DriverRemoteConnection extends RemoteConnection {
 
   /** @override */
   submit(bytecode) {
-    return this._client.submit(bytecode).then(result => new RemoteTraversal(result.toArray()));
+    let optionsStrategy = bytecode.sourceInstructions.find(
+        i => i[0] === "withStrategies" && i[1] instanceof OptionsStrategy);
+    const allowedKeys = ['evaluationTimeout', 'scriptEvaluationTimeout', 'batchSize', 'requestId', 'userAgent'];
+
+    let requestOptions = undefined;
+    if (optionsStrategy !== undefined) {
+      requestOptions = {};
+      const conf = optionsStrategy[1].configuration;
+      for (let key in conf) {
+        if (conf.hasOwnProperty(key) && allowedKeys.indexOf(key) > -1) {
+          requestOptions[key] = conf[key];
+        }
+      }
+    }
+    return this._client.submit(bytecode, null, requestOptions).then(result => new RemoteTraversal(result.toArray()));
   }
 
   /** @override */
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
index b0e91f2..1e19609 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/graph-traversal.js
@@ -26,7 +26,7 @@ const { Traversal } = require('./traversal');
 const remote = require('../driver/remote-connection');
 const utils = require('../utils');
 const Bytecode = require('./bytecode');
-const { TraversalStrategies, VertexProgramStrategy } = require('./traversal-strategy');
+const { TraversalStrategies, VertexProgramStrategy, OptionsStrategy } = require('./traversal-strategy');
 
 
 /**
@@ -77,6 +77,26 @@ class GraphTraversalSource {
   }
 
   /**
+   * Graph Traversal Source with method.
+   * @param {String} key
+   * @param {Object} value if not specified, the value with default to {@code true}
+   * @returns {GraphTraversalSource}
+   */
+  with_(key, value=undefined) {
+    const val = value === undefined ? true : value;
+    let optionsStrategy = this.bytecode.sourceInstructions.find(
+        i => i[0] === "withStrategies" && i[1] instanceof OptionsStrategy);
+    if (optionsStrategy === undefined) {
+      optionsStrategy = new OptionsStrategy({[key]: val});
+      return this.withStrategies(optionsStrategy);
+    } else {
+      optionsStrategy[1].configuration[key] = val;
+      return new this.graphTraversalSourceClass(this.graph, new TraversalStrategies(this.traversalStrategies),
+          this.bytecode, this.graphTraversalSourceClass, this.graphTraversalClass);
+    }
+  }
+
+  /**
    * Returns the string representation of the GraphTraversalSource.
    * @returns {string}
    */
@@ -85,16 +105,6 @@ class GraphTraversalSource {
   }
   
   /**
-   * Graph Traversal Source with method.
-   * @param {...Object} args
-   * @returns {GraphTraversalSource}
-   */
-  with_(...args) {
-    const b = new Bytecode(this.bytecode).addSource('with', args);
-    return new this.graphTraversalSourceClass(this.graph, new TraversalStrategies(this.traversalStrategies), b, this.graphTraversalSourceClass, this.graphTraversalClass);
-  }
-  
-  /**
    * Graph Traversal Source withBulk method.
    * @param {...Object} args
    * @returns {GraphTraversalSource}
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal-strategy.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal-strategy.js
index 301eb07..37816bd 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal-strategy.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/process/traversal-strategy.js
@@ -22,6 +22,8 @@
  */
 'use strict';
 
+const Traversal = require('./traversal').Traversal;
+
 class TraversalStrategies {
   /**
    * Creates a new instance of TraversalStrategies.
@@ -60,9 +62,9 @@ class TraversalStrategy {
 
   /**
    * @param {String} fqcn fully qualified class name in Java of the strategy
-   * @param {Map} configuration for the strategy
+   * @param {Object} configuration for the strategy
    */
-  constructor(fqcn, configuration = new Map()) {
+  constructor(fqcn, configuration = {}) {
     this.fqcn = fqcn;
     this.configuration = configuration;
   }
@@ -97,12 +99,12 @@ class HaltedTraverserStrategy extends TraversalStrategy {
   constructor(haltedTraverserFactory) {
     super("org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy");
     if (haltedTraverserFactory !== undefined)
-      this.configuration.set("haltedTraverserFactory", haltedTraverserFactory);
+      this.configuration["haltedTraverserFactory"] = haltedTraverserFactory;
   }
 }
 
 class OptionsStrategy extends TraversalStrategy {
-  constructor(options = new Map()) {
+  constructor(options) {
     super("org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy", options);
   }
 }
@@ -116,15 +118,7 @@ class PartitionStrategy extends TraversalStrategy {
    * @param {boolean} [options.includeMetaProperties] determines if meta-properties should be included in partitioning defaulting to false
    */
   constructor(options) {
-    super("org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy");
-    if (options.partitionKey !== undefined)
-      this.configuration.set("partitionKey", options.partitionKey);
-    if (options.writePartition !== undefined)
-      this.configuration.set("writePartition", options.writePartition);
-    if (options.readPartitions !== undefined)
-      this.configuration.set("readPartitions", options.readPartitions);
-    if (options.includeMetaProperties !== undefined)
-      this.configuration.set("includeMetaProperties", options.includeMetaProperties);
+    super("org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy", options);
   }
 }
 
@@ -137,39 +131,20 @@ class SubgraphStrategy extends TraversalStrategy {
    * @param {boolean} [options.checkAdjacentVertices] enables the strategy to apply the {@code vertices} filter to the adjacent vertices of an edge.
    */
   constructor(options) {
-    super("org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy");
-    if (options.vertices !== undefined)
-      this.configuration.set("vertices", options.vertices);
-    if (options.edges !== undefined)
-      this.configuration.set("edges", options.edges);
-    if (options.vertexProperties !== undefined)
-      this.configuration.set("vertexProperties", options.vertexProperties);
-    if (options.checkAdjacentVertices !== undefined)
-      this.configuration.set("checkAdjacentVertices", options.checkAdjacentVertices);
+    super("org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy", options);
+    if (this.configuration.vertices instanceof Traversal)
+      this.configuration.vertices = this.configuration.vertices.bytecode;
+    if (this.configuration.edges instanceof Traversal)
+      this.configuration.edges = this.configuration.edges.bytecode;
+    if (this.configuration.vertexProperties instanceof Traversal)
+      this.configuration.vertexProperties = this.configuration.vertexProperties.bytecode;
   }
 }
 
 class VertexProgramStrategy extends TraversalStrategy {
 
   constructor(options) {
-    super("org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy");
-    this.configuration = new Map();
-    if (options.graphComputer !== undefined)
-      this.configuration.set("graphComputer", options.graphComputer);
-    if (options.workers !== undefined)
-      this.configuration.set("workers", options.workers);
-    if (options.persist !== undefined)
-      this.configuration.set("persist", options.persist);
-    if (options.result !== undefined)
-      this.configuration.set("result", options.result);
-    if (options.vertices !== undefined)
-      this.configuration.set("vertices", options.vertices);
-    if (options.edges !== undefined)
-      this.configuration.set("edges", options.edges);
-    if (options.configuration !== undefined)
-      options.configuration.forEach(function(k,v) {
-        this.configuration.set(k, v);
-      });
+    super("org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy", options);
   }
 }
 
@@ -179,8 +154,8 @@ class MatchAlgorithmStrategy extends TraversalStrategy {
    */
   constructor(matchAlgorithm) {
     super("org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy");
-    if (graphComputer !== undefined)
-      this.configuration.set("matchAlgorithm", matchAlgorithm);
+    if (matchAlgorithm !== undefined)
+      this.configuration["matchAlgorithm"] = matchAlgorithm;
   }
 }
 
@@ -286,9 +261,8 @@ class EdgeLabelVerificationStrategy extends TraversalStrategy {
    * @param {boolean} throwException determines if exceptions should be thrown when verifications fails
    */
   constructor(logWarnings = false, throwException=false) {
-    super("org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.EdgeLabelVerificationStrategy");
-    this.configuration.set("logWarnings", logWarnings);
-    this.configuration.set("throwException", throwException);
+    super("org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.EdgeLabelVerificationStrategy",
+        {logWarnings: logWarnings, throwException: throwException});
   }
 }
 
@@ -299,10 +273,8 @@ class ReservedKeysVerificationStrategy extends TraversalStrategy {
    * @param {Array<String>} keys the list of reserved keys to verify
    */
   constructor(logWarnings = false, throwException=false, keys=["id", "label"]) {
-    super("org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.EdgeLabelVerificationStrategy");
-    this.configuration.set("logWarnings", logWarnings);
-    this.configuration.set("throwException", throwException);
-    this.configuration.set("keys", keys);
+    super("org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.EdgeLabelVerificationStrategy",
+        {logWarnings: logWarnings, throwException: throwException, keys: keys});
   }
 }
 
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
index b172749..47e9407 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/lib/structure/io/type-serializers.js
@@ -256,9 +256,16 @@ class TraverserSerializer extends TypeSerializer {
 class TraversalStrategySerializer extends TypeSerializer {
   /** @param {TraversalStrategy} item */
   serialize(item) {
+    const conf = {};
+    for (let k in item.configuration) {
+      if (item.configuration.hasOwnProperty(k)) {
+        conf[k] = this.writer.adaptObject(item.configuration[k]);
+      }
+    }
+
     return {
       [typeKey]: 'g:' + item.constructor.name,
-      [valueKey]: item.configuration
+      [valueKey]: conf
     };
   }
 
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/traversal-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/traversal-test.js
index cfa99dd..39c675f 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/traversal-test.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/integration/traversal-test.js
@@ -153,19 +153,19 @@ describe('Traversal', function () {
       g.V().count().next().then(function (item1) {
         assert.ok(item1);
         assert.strictEqual(item1.value, 4);
-      });
+      }, (err) => assert.fail("tanked: " + err));
       g.E().count().next().then(function (item1) {
         assert.ok(item1);
         assert.strictEqual(item1.value, 0);
-      });
+      }, (err) => assert.fail("tanked: " + err));
       g.V().label().dedup().count().next().then(function (item1) {
         assert.ok(item1);
         assert.strictEqual(item1.value, 1);
-      });
+      }, (err) => assert.fail("tanked: " + err));
       g.V().label().dedup().next().then(function (item1) {
         assert.ok(item1);
         assert.strictEqual(item1.value, "person");
-      });
+      }, (err) => assert.fail("tanked: " + err));
     });
     it('should allow ReadOnlyStrategy', function() {
       const g = traversal().withRemote(connection).withStrategies(new ReadOnlyStrategy());
@@ -181,7 +181,11 @@ describe('Traversal', function () {
         assert.ok(item1);
         assert.strictEqual(item1.value, 6);
       });
-      return g.V().out().iterate().then(() => assert.fail("should have tanked"), (err) => assert.ok(err));
+      return g.V().out().iterate().then(() => assert.fail("should have tanked"), (err) => assert.strictEqual(err.statusCode, 500));
+    });
+    it('should allow with_(evaluationTimeout,10)', function() {
+      const g = traversal().withRemote(connection).with_('x').with_('evaluationTimeout', 10);
+      return g.V().repeat(__.both()).iterate().then(() => assert.fail("should have tanked"), (err) => assert.strictEqual(err.statusCode, 598));
     });
   });
 });
\ No newline at end of file
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/traversal-test.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/traversal-test.js
index acdcdd4..2ab18ee 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/traversal-test.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/unit/traversal-test.js
@@ -57,43 +57,20 @@ describe('Traversal', function () {
       assert.strictEqual(bytecode.stepInstructions[2][2].typeName, 'Order');
       assert.strictEqual(bytecode.stepInstructions[2][2].elementName, 'desc');
     });
-  });
 
-  // describe('#hasNext()', function() {
-  //   it('should apply strategies and determine if there is anything left to iterate in the traversal')
-  //   const strategyMock = {
-  //     apply: function (traversal) {
-  //       traversal.traversers = [ new t.Traverser(1, 1), new t.Traverser(2, 1) ];
-  //       return Promise.resolve();
-  //     }
-  //   };
-  //   const strategies = new TraversalStrategies();
-  //   strategies.addStrategy(strategyMock);
-  //   const traversal = new t.Traversal(null, strategies, null);
-  //   return traversal.hasNext()
-  //       .then(function (more) {
-  //         assert.strictEqual(more, true);
-  //         return traversal.next();
-  //       })
-  //       .then(function (item) {
-  //         assert.strictEqual(item.value, 1);
-  //         assert.strictEqual(item.done, false);
-  //         return traversal.next();
-  //       })
-  //       .then(function (item) {
-  //         assert.strictEqual(item.value, 2);
-  //         assert.strictEqual(item.done, false);
-  //         return traversal.next();
-  //       })
-  //       .then(function (item) {
-  //         assert.strictEqual(item.value, null);
-  //         assert.strictEqual(item.done, true);
-  //         return traversal.hasNext();
-  //       })
-  //       .then(function (more) {
-  //         assert.strictEqual(more, false);
-  //       });
-  // });
+    it('should configure OptionStrategy for with_()', function () {
+      const g = new graph.Graph().traversal();
+      const bytecode = g.with_('x','test').with_('y').V().getBytecode();
+      assert.ok(bytecode);
+      assert.strictEqual(bytecode.sourceInstructions.length, 1);
+      assert.strictEqual(bytecode.sourceInstructions[0][0], 'withStrategies');
+      const conf = bytecode.sourceInstructions[0][1].configuration;
+      assert.strictEqual(conf.x, 'test');
+      assert.strictEqual(conf.y, true);
+      assert.strictEqual(bytecode.stepInstructions.length, 1);
+      assert.strictEqual(bytecode.stepInstructions[0][0], 'V');
+    });
+  });
 
   describe('#next()', function () {
     it('should apply the strategies and return a Promise with the iterator item', function () {