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