[ https://issues.apache.org/jira/browse/TINKERPOP-1278?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15260780#comment-15260780 ]
Marko A. Rodriguez commented on TINKERPOP-1278: ----------------------------------------------- The problem of testing. I think I have an idea. Lets look at standard old Gremlin-Java {{SumTest}}. {code} public abstract class SumTest { // ... public static class Traversals extends SumTest { @Override public Traversal<Vertex, Double> get_g_V_valuesXageX_sum() { g.V().values("age").sum(); } // ... } } {code} We create an interface (or abstract class) called {{VariantConverter}} which does the following: {code} public class PythonVariantConverter extends VariantConverter { public String concat() { return "."; } public String source(final String source) { return source; } public String step(String stepName, final Object... arguments) { if(stepName.equals("values") && arguments.length == 1) return arguments[0].toString(); else if(stepName.equals("as") || stepName.equals("from") || ...) return "_" + stepName + "(" + Arrays.asStrings(arguments) + ")"; else return stepName + "(" + Arrays.asString(arguments) + ")"; } // probably more stuff.. like lambdas and P, Order, etc. stuffs. } {code} Then we will have a {{GraphTraversalSource}} and {{GraphTraversal}} implementation in Java that DOES NOT do all the {{addStep}}-stuff, but instead, uses the {{VariantConverter}} to generate a string representation of the traversal for that variant's host language. Thus, the Gremlin-Java test suite is used, but realize that the {{g.V().values("age").sum()}} call is creating a {{String}} in the host language, which is then evaluated to generate a Gremlin-Groovy string, which is then evaluated by Groovy to generate a {{Traversal}}. And that ultimate {{Traversal}} is then what is tested (i.e. returned from {{get_g_V_valuesXageX_sum()}}). Thus, something like this...(and we only need to test these against TinkerGraph -- both OLTP and OLAP). {code} public class TinkerGraphGremlinPythonProvider extends AbstractGraphProvider { private final VariantConverter converter = new PythonVariantConverter(); @Override public default GraphTraversalSource traversal(final Graph graph) { return new VariantGraphTraversalSource(graph, converter); } } {code} Again: * {{VariantGraphTraversalSource}} and {{VariantGraphTraversal}} generate a Python string as instructed by {{PythonVariantConverter}}. * The Python string is evaluated in Jython (or CPython with some {{System.eval()}}-magic) which generates a Gremlin-Groovy string. * That Gremlin-Groovy string is evaluated by {{GremlinGroovyScriptEngine}} which generates a {{Traversal}}. * That {{Traversal}} is returned by the respective {{XXXTest.g_V_outXknowsX_sum_xxxxxx()}}-test and thus, tested. Thus, for us (TinkerPop) all we need to do is create: {code} VariantGraphTraversalSource // reusable for all variants VariantGraphTraversal // reusable for all variants Variant__ // reusable for all variants // probably can make this a Groovy class and just have it use meta-programming! easy peasy. -------------------------------- TinkerGraphGremlinPythonProvider PythonVariantConverter // manually coded but its not much gremlin-python.py // generated via reflection on each "mvn clean install" -------------------------------- TinkerGraphGremlinRubyProvider RubyVariantConverter // manually coded but its not much gremlin_ruby.rb // generated via reflection on each "mvn clean install" -------------------------------- TinkerGraphGremlinPHPProvider PHPVariantConverter // manually coded but its not much Gremlin_PHP.php // generated via reflection on each "mvn clean install" {code} > Support at least 3 Gremlin language variants. > --------------------------------------------- > > Key: TINKERPOP-1278 > URL: https://issues.apache.org/jira/browse/TINKERPOP-1278 > Project: TinkerPop > Issue Type: Improvement > Affects Versions: 3.2.0-incubating > Reporter: Marko A. Rodriguez > > As discussed on dev@... > Apache TinkerPop should provide, out-of-the-box, at least 3 Gremlin language > variants. It would be cool if these were: > * Python (Mark Henderson) > * PHP ([~PommeVerte]) > * Ruby (?[~okram]) > I think each of these should be generated using the reflection-model > presented in > http://tinkerpop.apache.org/docs/3.2.1-SNAPSHOT/tutorials/gremlin-language-variants/. > Moreover, on every {{mvn clean install}}, the code for these variants is > generated. > Given the desire to separate language variants from language drivers, I think > that a language driver for each variant above should be "plugable." Moreover, > we should provide one driver implementation for each -- simple GremlinServer > REST. > {code} > gremlin-variants/ > gremlin-ruby/ > gremlin_ruby.rb > gremlin_ruby_rest_driver.rb > gremlin-php/ > Gremlin_PHP.php > Gremlin_PHP_REST_Driver.php > gremlin-python/ > gremlin-python.py > gremlin-python-rest-driver.py > {code} > Next, each variant implementation should be testable. This is PAINFUL if we > have to implement each {{g_V_out_repeatXasXaXX}} test case in > {{ProcessXXXSuite}}. Perhaps some RegEx transducer magic could be used to > convert all those tests from Gremlin-Java to the respective host language? > However, even if we do that, we still have the problem of how to test the > returned results. > I think what we should test the returned results using the JVM. For instance, > JRuby, Jython, JPHP (does it exist?). If we do this, we will save ourselves a > massive headache. All we have to do is create a {{GraphProvider}} that uses > {{TinkerGraph}} and whose {{TraversalSource}} is some sort of wrapper around > reflection-generated Ruby (e.g.). > {code} > g.V.out_e("knows") // returns a Ruby iterator > {code} > That Ruby iterator should be converted to a Java iterator and then the > {{ProcessXXXSuite}} can verify the results. > With this, most everything is reflectively constructed. > {code} > gremlin_ruby.rb // generated via Java reflection > gremlin_ruby_rest_driver.rb // manually coded > match_test.rb // generated via RegEx transducer > has_test.rb // generated via RegEx transducer > ... > RubyGraphProvider.java // manually coded > RubyProcessStandardSuite.java // manually coded > RubyProcessComputerSuite.java // manually coded > {code} > Thus, the testing data flow would be: > {code} > MatchTest.Traversals.java --transducer-> match_test.rb > match-test.rb --REST--> GremlinServer > GremlinServer --GraphSON-->match-test.rb > GraphSON --JRuby/GraphSONReader-->Java objects > Java objects --JRuby-->MatchTest.java > {code} -- This message was sent by Atlassian JIRA (v6.3.4#6332)