[ 
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)

Reply via email to