From beb0b091de456867b5ee8ac2e25c42133f442a1d Mon Sep 17 00:00:00 2001
From: Anders Blomdell <anders.blomdell@control.lth.se>
Date: Mon, 25 May 2015 21:55:09 +0200
Subject: [PATCH] Preparing for cross language checks of renaming
 encoders/decoders

---
 test/Makefile                         |  32 +++-
 test/relay_gen_c.py                   |  89 +++++++--
 test/test_renaming_encoder_decoder.py | 253 ++++++++++++++++++++++++++
 3 files changed, 354 insertions(+), 20 deletions(-)
 create mode 100755 test/test_renaming_encoder_decoder.py

diff --git a/test/Makefile b/test/Makefile
index dab650b..456cc4e 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -8,7 +8,7 @@ include ../lib/c/os_compat.mk
 
 all:
 
-test: $(TESTS:%=test_%) compiler_errors
+test: $(TESTS:%=test_%) $(TESTS:%=test_renaming_%) compiler_errors
 #	PYTHONPATH=../lib/python \
 #		./test_encoder_decoder.py --labcomm="$(LABCOMM)" basic.lc
 
@@ -29,8 +29,25 @@ test_%: gen/%/signatures.py \
 		--test $(shell echo $(VALGRIND) | sed -e 's/[-][-]/\\\\--/g') \
 		       gen/$*/c_relay /dev/stdin /dev/stdout \
 		--test mono gen/$*/cs_relay.exe /dev/stdin /dev/stdout \
-		--test java \\-cp gen/$*:../lib/java/labcomm2014.jar java_relay \
-			    /dev/stdin /dev/stdout
+		--test java \\-cp gen/$*:../lib/java/labcomm2014.jar \
+		       java_relay /dev/stdin /dev/stdout
+
+.PHONY: test_renaming_%
+test_renaming_%: gen/%/signatures.py \
+		gen/%/c_renaming_relay \
+		gen/%/cs_relay.exe \
+		gen/%/java_relay.class \
+		gen/%/java_code
+	PYTHONPATH=$(PYTHONPATH) MONO_PATH=$(MONO_PATH) \
+		./test_renaming_encoder_decoder.py \
+		--signatures=gen/$*/signatures.py \
+		--test tee gen/$*/testdata.renamed \
+		--test $(shell echo $(VALGRIND) | sed -e 's/[-][-]/\\\\--/g') \
+		       gen/$*/c_renaming_relay /dev/stdin /dev/stdout
+	echo \
+		--test mono gen/$*/cs_relay.exe /dev/stdin /dev/stdout \
+		--test java \\-cp gen/$*:../lib/java/labcomm2014.jar \
+		       java_relay /dev/stdin /dev/stdout
 
 # test cases for compiler error checking
 .PHONY: compiler_errors testErrorsOK testErrorsNOK
@@ -72,6 +89,15 @@ gen/%/c_relay: gen/%/c_relay.c gen/%/c_code.c Makefile
 	$(CC) $(CFLAGS) -o $@ $< -I../lib/c/2014 -I. -L../lib/c \
 		gen/$*/c_code.c -llabcomm2014
 
+.PRECIOUS: gen/%/c_renaming_relay.c
+gen/%/c_renaming_relay.c: gen/%/typeinfo relay_gen_c.py Makefile
+	./relay_gen_c.py --renaming $< > $@
+
+.PRECIOUS: gen/%/c_renaming_relay
+gen/%/c_renaming_relay: gen/%/c_renaming_relay.c gen/%/c_code.c Makefile
+	$(CC) $(CFLAGS) -o $@ $< -I../lib/c/2014 -I. -L../lib/c \
+		gen/$*/c_code.c -llabcomm2014
+
 # C# relay test rules
 .PRECIOUS: gen/%/cs_code.cs
 gen/%/cs_code.cs: %.lc Makefile | gen/%/.dir
diff --git a/test/relay_gen_c.py b/test/relay_gen_c.py
index 2706d34..e13f66a 100755
--- a/test/relay_gen_c.py
+++ b/test/relay_gen_c.py
@@ -1,5 +1,6 @@
 #!/usr/bin/python
 
+import argparse
 import re
 import sys
 
@@ -13,7 +14,13 @@ def split_match(pattern, multiline):
    
 
 if __name__ == '__main__':
-    f = open(sys.argv[1])
+    parser = argparse.ArgumentParser(description='Generate C test relay.')
+    parser.add_argument('--renaming', action='store_true')
+    parser.add_argument('typeinfo', help='typeinfo file')
+
+    options = parser.parse_args(sys.argv[1:])
+
+    f = open(options.typeinfo)
     sample = []
     for l in map(lambda s: s.strip(), f):
         lang,kind,func,arg,stype = l[1:].split(l[0])
@@ -27,12 +34,21 @@ if __name__ == '__main__':
       |#include <sys/types.h>
       |#include <sys/stat.h>
       |#include <fcntl.h>
+      |#include <stdio.h>
       |#include <labcomm2014.h>
       |#include <labcomm2014_default_error_handler.h>
       |#include <labcomm2014_default_memory.h>
       |#include <labcomm2014_default_scheduler.h>
       |#include <labcomm2014_fd_reader.h>
       |#include <labcomm2014_fd_writer.h>
+    """))
+    if options.renaming:
+        result.extend(split_match('^[^|]*\|(.*)$', """
+        |#include "labcomm2014_renaming.h"
+        |#include "labcomm2014_renaming_encoder.h"
+        |#include "labcomm2014_renaming_decoder.h"
+        """))
+    result.extend(split_match('^[^|]*\|(.*)$', """
       |#include "c_code.h"
     """))
     for func,arg,stype in sample:
@@ -45,26 +61,55 @@ if __name__ == '__main__':
         pass
     result.extend(split_match('^[^|]*\|(.*)$', """
       |int main(int argc, char *argv[]) {
-      |  struct labcomm2014_encoder *e;
-      |  struct labcomm2014_decoder *d;
-      |  int in, out;
+      |  struct labcomm2014_encoder *e, *e_e;
+      |  struct labcomm2014_decoder *d, *d_d;
+    """))
+    if options.renaming:
+        result.extend(split_match('^[^|]*\|(.*)$', """
+        |  struct labcomm2014_encoder *e_p, *e_s;
+        |  struct labcomm2014_decoder *d_p, *d_s;
+        """))
+    result.extend(split_match('^[^|]*\|(.*)$', """
+      |  int in, out, result;
       |  
       |  if (argc < 3) { return 1; }
       |  in = open(argv[1], O_RDONLY);
       |  if (in < 0) { return 1; }
       |  out = open(argv[2], O_WRONLY);
       |  if (out < 0) { return 1; }
-      |  e = labcomm2014_encoder_new(labcomm2014_fd_writer_new(
-      |                              labcomm2014_default_memory, out, 1), 
-      |                              labcomm2014_default_error_handler,
-      |                              labcomm2014_default_memory,
-      |                              labcomm2014_default_scheduler);
-      |  d = labcomm2014_decoder_new(labcomm2014_fd_reader_new(
-      |                              labcomm2014_default_memory, in, 1), 
-      |                              labcomm2014_default_error_handler,
-      |                              labcomm2014_default_memory,
-      |                              labcomm2014_default_scheduler);
+      |  e_e = labcomm2014_encoder_new(labcomm2014_fd_writer_new(
+      |                                labcomm2014_default_memory, out, 1),
+      |                                labcomm2014_default_error_handler,
+      |                                labcomm2014_default_memory,
+      |                                labcomm2014_default_scheduler);
+      |  d_d = labcomm2014_decoder_new(labcomm2014_fd_reader_new(
+      |                                labcomm2014_default_memory, in, 1),
+      |                                labcomm2014_default_error_handler,
+      |                                labcomm2014_default_memory,
+      |                                labcomm2014_default_scheduler);
     """))
+    if not options.renaming:
+        result.extend(split_match('^[^|]*\|(.*)$', """
+        |  e = e_e;
+        |  d = d_d;
+        """))
+    else:
+        result.extend(split_match('^[^|]*\|(.*)$', """
+        |  e_p = labcomm2014_renaming_encoder_new(e_e,
+        |                                         labcomm2014_renaming_prefix,
+        |                                         "prefix:");
+        |  e_s = labcomm2014_renaming_encoder_new(e_p,
+        |                                         labcomm2014_renaming_suffix,
+        |                                         ":suffix");
+        |  e = e_s;
+        |  d_p = labcomm2014_renaming_decoder_new(d_d,
+        |                                         labcomm2014_renaming_prefix,
+        |                                         "prefix:");
+        |  d_s = labcomm2014_renaming_decoder_new(d_p,
+        |                                         labcomm2014_renaming_suffix,
+        |                                         ":suffix");
+        |  d = d_s;
+        """))
     for func,arg,stype in sample:
         result.extend(split_match('^[^|]*\|(.*)$', """
           |  labcomm2014_encoder_register_%(func)s(e);
@@ -73,9 +118,19 @@ if __name__ == '__main__':
           |  labcomm2014_decoder_sample_ref_register(d, labcomm2014_signature_%(func)s);
        """ % { 'func': func, 'arg': arg }))
     result.extend(split_match('^[^|]*\|(.*)$', """
-      |  labcomm2014_decoder_run(d);
-      |  labcomm2014_decoder_free(d);
-      |  labcomm2014_encoder_free(e);
+      |  while ((result = labcomm2014_decoder_decode_one(d)) > 0) {};
+    """))
+    if options.renaming:
+        result.extend(split_match('^[^|]*\|(.*)$', """
+        |  labcomm2014_decoder_free(d_s);
+        |  labcomm2014_decoder_free(d_p);
+        |  labcomm2014_encoder_free(e_s);
+        |  labcomm2014_encoder_free(e_p);
+        """))
+    result.extend(split_match('^[^|]*\|(.*)$', """
+      |  labcomm2014_decoder_free(d_d);
+      |  labcomm2014_encoder_free(e_e);
+      |  fprintf(stderr, "Failed with %d", result);
       |  return 0;
       |}
     """))
diff --git a/test/test_renaming_encoder_decoder.py b/test/test_renaming_encoder_decoder.py
new file mode 100755
index 0000000..8f623f8
--- /dev/null
+++ b/test/test_renaming_encoder_decoder.py
@@ -0,0 +1,253 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import argparse
+import imp
+import labcomm2014
+import math
+import os
+import re
+import struct
+import subprocess
+import sys
+import threading
+
+
+def labcomm_compile(lc, name, args):
+    for lang in [ 'c', 'csharp', 'java', 'python']:
+        destdir = 'gen/%s/%s' % (name, lang)
+        if not os.path.exists(destdir):
+            os.makedirs(destdir)
+            pass
+        pass
+    cmd = args.labcomm.split() + [ 
+        "--c=gen/%s/c/%s.c" % (name, name),
+        "--h=gen/%s/c/%s.h" % (name, name),
+        "--cs=gen/%s/csharp/%s.cs" % (name, name),
+        "--python=gen/%s/python/%s.py" % (name, name),
+        "--java=gen/%s/java/" % name,
+        "--typeinfo=gen/%s/%s.typeinfo" % (name, name),
+        lc]
+    subprocess.check_call(cmd)
+    pass
+
+def get_signatures(path):
+    fp, pathname, description = imp.find_module(os.path.basename(path)[0:-3], 
+                                                [ os.path.dirname(path) ])
+    with fp as fp:
+        m = imp.load_module('signatures', fp, pathname, description)
+        pass
+    return map(lambda s: s.signature, m.sample)
+
+class Test:
+    
+    def __init__(self, program, signatures):
+        self.program = program
+        self.signatures = map(lambda s: s.rename('prefix:%s:suffix' % s.name),
+                              signatures)
+        pass
+
+    def generate(self, decl):
+        if decl.__class__ == labcomm2014.sample:
+            result = []
+            for values in self.generate(decl.decl):
+                result.append((decl, values))
+            return result
+    
+        elif decl.__class__ == labcomm2014.typedef:
+            result = []
+            for values in self.generate(decl.decl):
+                result.append(values)
+            return result
+
+        elif decl.__class__ == labcomm2014.struct:
+            result = []
+            if len(decl.field) == 0:
+                result.append({})
+            else:
+                values1 = self.generate(decl.field[0][1])
+                values2 = self.generate(labcomm2014.struct(decl.field[1:]))
+                for v1 in values1:
+                    for v2 in values2:
+                        v = dict(v2)
+                        v[decl.field[0][0]] = v1
+                        result.append(v)
+            return result
+        
+        elif decl.__class__ == labcomm2014.array:
+            if len(decl.indices) == 1:
+                values = self.generate(decl.decl)
+                if decl.indices[0] == 0:
+                    lengths = [0, 1, 2]
+                else:
+                    lengths = [ decl.indices[0] ]
+            else:
+                values = self.generate(labcomm2014.array(decl.indices[1:],
+                                                     decl.decl))
+                if decl.indices[0] == 0:
+                    lengths = [1, 2]
+                else:
+                    lengths = [ decl.indices[0] ]
+            result = []
+            for v in values:
+                for i in lengths:
+                    element = []
+                    for j in range(i):
+                        element.append(v)
+                    result.append(element)
+            return result
+    
+        elif decl.__class__ == labcomm2014.BOOLEAN:
+            return [False, True]
+    
+        elif decl.__class__ == labcomm2014.BYTE:
+            return [0, 127, 128, 255]
+    
+        elif decl.__class__ == labcomm2014.SHORT:
+            return [-32768, 0, 32767]
+    
+        elif decl.__class__ == labcomm2014.INTEGER:
+            return [-2147483648, 0, 2147483647]
+    
+        elif decl.__class__ == labcomm2014.LONG:
+            return [-9223372036854775808, 0, 9223372036854775807]
+    
+        elif decl.__class__ == labcomm2014.FLOAT:
+            def tofloat(v):
+                return struct.unpack('f', struct.pack('f', v))[0]
+            return [tofloat(-math.pi), 0.0, tofloat(math.pi)]
+    
+        elif decl.__class__ == labcomm2014.DOUBLE:
+            return [-math.pi, 0.0, math.pi]
+    
+        elif decl.__class__ == labcomm2014.STRING:
+            return ['string', u'sträng' ]
+    
+        elif decl.__class__ == labcomm2014.SAMPLE:
+            return self.signatures
+    
+        print>>sys.stderr, decl
+        raise Exception("unhandled decl %s" % decl.__class__)
+
+    def uses_refs(self, decls):
+        for decl in decls:
+            if decl.__class__ == labcomm2014.sample:
+                if self.uses_refs([ decl.decl ]):
+                    return True
+    
+            elif decl.__class__ == labcomm2014.struct:
+                if self.uses_refs([ d for n,d in decl.field ]):
+                    return True
+        
+            elif decl.__class__ == labcomm2014.array:
+                if self.uses_refs([ decl.decl ]):
+                    return True
+
+            elif decl.__class__ == labcomm2014.SAMPLE:
+                return True
+
+        return False
+        
+
+    def run(self):
+        print>>sys.stderr, 'Testing', self.program
+        p = subprocess.Popen(self.program, 
+                             stdin=subprocess.PIPE,
+                             stdout=subprocess.PIPE,
+                             stderr=sys.stderr)
+        self.expected = None
+        self.failed = False
+        self.next = threading.Condition()
+        decoder = threading.Thread(target=self.decode, args=(p.stdout,))
+        decoder.start()
+        encoder = labcomm2014.Encoder(labcomm2014.StreamWriter(p.stdin))
+        for signature in self.signatures:
+            encoder.add_decl(signature)
+            pass
+        if self.uses_refs(self.signatures):
+            for signature in self.signatures:
+                encoder.add_ref(signature)
+        for signature in self.signatures:
+            print>>sys.stderr, "Checking", signature.name,
+            for decl,value in self.generate(signature):
+                sys.stderr.write('.')
+                self.next.acquire()
+                self.received_value = None
+                self.received_decl = None
+                encoder.encode(value, decl)
+                self.next.wait(2)
+                self.next.release()
+                if p.poll() != None:
+                    print>>sys.stderr, "Failed with:", p.poll()
+                    self.failed = True
+                elif value != self.received_value:
+                    print>>sys.stderr, "Coding error"
+                    print>>sys.stderr, value == self.received_value
+                    print>>sys.stderr, "Got:     ", self.received_value 
+                    print>>sys.stderr, "         ", self.received_decl 
+                    print>>sys.stderr, "Expected:", value
+                    print>>sys.stderr, "         ", decl
+                    self.failed = True
+                    
+                if self.failed: 
+                    if p.poll() == None:
+                        p.terminate()
+                    exit(1)
+                pass
+            print>>sys.stderr
+            pass
+        p.stdin.close()
+        if p.wait() != 0:
+            exit(1)
+            pass
+        pass
+
+    def decode(self, f):
+        decoder = labcomm2014.Decoder(labcomm2014.StreamReader(f))
+        try:
+            while True:
+                value,decl = decoder.decode()
+                if value != None:
+                    self.next.acquire()
+                    self.received_value = value
+                    self.received_decl = decl
+                    self.expected = None
+                    self.next.notify_all()
+                    self.next.release()
+                pass
+            pass
+        except EOFError:
+            pass
+        pass
+
+    pass
+    
+def run(test, signatures):
+    t = Test(test, signatures)
+    t.run()
+    pass
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser(description='Run encoding test.')
+    class test_action(argparse.Action):
+        def __call__(self, parser, namespace, values, option_string=None):
+            old = list(getattr(namespace, self.dest))
+            def strip_slash(s):
+                if s.startswith('\\'):
+                    return s[1:]
+                return s
+            old.append(map(strip_slash, values))
+            setattr(namespace, self.dest, old)
+    parser.add_argument('--signatures')
+    parser.add_argument('--test', nargs='*', action=test_action, default=[])
+
+    args = parser.parse_args()
+    signatures = get_signatures(args.signatures)
+    for test in args.test:
+        run(test, signatures)
+    exit(0)
+    
+    for lc in args.lc:
+        run(lc, args)
+        pass
+    pass
-- 
GitLab