Skip to content

Commit c49e757

Browse files
committed
Add test machinery for compile
1 parent 6f1f9b2 commit c49e757

File tree

3 files changed

+232
-0
lines changed

3 files changed

+232
-0
lines changed

compile/compile_data_test.go

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Test data generated by make_compile_test.py - do not edit
2+
3+
package compile
4+
5+
import (
6+
"github.com/ncw/gpython/py"
7+
)
8+
9+
var compileTestData = []struct {
10+
in string
11+
mode string // exec, eval or single
12+
out py.Code
13+
dis string
14+
}{
15+
{"pass", "exec", py.Code{
16+
Argcount: 0,
17+
Kwonlyargcount: 0,
18+
Nlocals: 0,
19+
Stacksize: 1,
20+
Flags: 64,
21+
Code: "\x64\x00\x00\x53",
22+
Consts: []py.Object{py.None},
23+
Names: []string{},
24+
Varnames: []string{},
25+
Freevars: []string{},
26+
Cellvars: []string{},
27+
Filename: "<string>",
28+
Name: "<module>",
29+
Firstlineno: 1,
30+
Lnotab: "",
31+
}, " 1 0 LOAD_CONST 0 (None)\n 3 RETURN_VALUE\n"},
32+
{"print(\"Hello World!\")", "eval", py.Code{
33+
Argcount: 0,
34+
Kwonlyargcount: 0,
35+
Nlocals: 0,
36+
Stacksize: 2,
37+
Flags: 64,
38+
Code: "\x65\x00\x00\x64\x00\x00\x83\x01\x00\x53",
39+
Consts: []py.Object{py.String("Hello World!")},
40+
Names: []string{"print"},
41+
Varnames: []string{},
42+
Freevars: []string{},
43+
Cellvars: []string{},
44+
Filename: "<string>",
45+
Name: "<module>",
46+
Firstlineno: 1,
47+
Lnotab: "",
48+
}, " 1 0 LOAD_NAME 0 (print)\n 3 LOAD_CONST 0 ('Hello World!')\n 6 CALL_FUNCTION 1 (1 positional, 0 keyword pair)\n 9 RETURN_VALUE\n"},
49+
}

compile/compile_test.go

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package compile
2+
3+
//go:generate ./make_compile_test.py
4+
5+
import (
6+
"testing"
7+
8+
"github.com/ncw/gpython/py"
9+
)
10+
11+
func EqStrings(t *testing.T, name string, a, b []string) {
12+
if len(a) != len(b) {
13+
t.Errorf("%s has differing length, want %v, got %v", name, a, b)
14+
}
15+
for i := range a {
16+
if a[i] != b[i] {
17+
t.Errorf("%s[%d] has differs, want %v, got %v", name, i, a, b)
18+
}
19+
}
20+
}
21+
22+
func EqCode(t *testing.T, a, b *py.Code) {
23+
// int32
24+
if a.Argcount != b.Argcount {
25+
t.Errorf("Argcount differs, want %d, got %d", a.Argcount, b.Argcount)
26+
}
27+
if a.Kwonlyargcount != b.Kwonlyargcount {
28+
t.Errorf("Kwonlyargcount differs, want %d, got %d", a.Kwonlyargcount, b.Kwonlyargcount)
29+
}
30+
if a.Nlocals != b.Nlocals {
31+
t.Errorf("Nlocals differs, want %d, got %d", a.Nlocals, b.Nlocals)
32+
}
33+
if a.Stacksize != b.Stacksize {
34+
t.Errorf("Stacksize differs, want %d, got %d", a.Stacksize, b.Stacksize)
35+
}
36+
if a.Flags != b.Flags {
37+
t.Errorf("Flags differs, want %d, got %d", a.Flags, b.Flags)
38+
}
39+
if a.Firstlineno != b.Firstlineno {
40+
t.Errorf("Firstlineno differs, want %d, got %d", a.Firstlineno, b.Firstlineno)
41+
}
42+
43+
// string
44+
if a.Code != b.Code {
45+
t.Errorf("Code differs, want %q, got %q", a.Code, b.Code)
46+
}
47+
if a.Filename != b.Filename {
48+
t.Errorf("Filename differs, want %q, got %q", a.Filename, b.Filename)
49+
}
50+
if a.Name != b.Name {
51+
t.Errorf("Name differs, want %q, got %q", a.Name, b.Name)
52+
}
53+
if a.Lnotab != b.Lnotab {
54+
t.Errorf("Lnotab differs, want %q, got %q", a.Lnotab, b.Lnotab)
55+
}
56+
57+
// Tuple
58+
// FIXME Consts
59+
60+
// []string
61+
EqStrings(t, "Names", a.Names, b.Names)
62+
EqStrings(t, "Varnames", a.Varnames, b.Varnames)
63+
EqStrings(t, "Freevars", a.Freevars, b.Freevars)
64+
EqStrings(t, "Cellvars", a.Cellvars, b.Cellvars)
65+
66+
// []byte
67+
// Cell2arg
68+
}
69+
70+
func TestCompile(t *testing.T) {
71+
for _, test := range compileTestData {
72+
codeObj := Compile(test.in, "<string>", test.mode, 0, true)
73+
code, ok := codeObj.(*py.Code)
74+
if !ok {
75+
t.Fatalf("Expecting *py.Code but got %T", codeObj)
76+
}
77+
EqCode(t, &test.out, code)
78+
}
79+
}

compile/make_compile_test.py

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env python3.4
2+
"""
3+
Write compile_data_test.go
4+
"""
5+
6+
import sys
7+
import ast
8+
import subprocess
9+
import dis
10+
11+
inp = [
12+
('''pass''', "exec"),
13+
('''print("Hello World!")''', "eval"),
14+
]
15+
16+
def string(s):
17+
if isinstance(s, str):
18+
return '"%s"' % s
19+
elif isinstance(s, bytes):
20+
out = '"'
21+
for b in s:
22+
out += "\\x%02x" % b
23+
out += '"'
24+
return out
25+
else:
26+
raise AssertionError("Unknown string %r" % s)
27+
28+
def strings(ss):
29+
"""Dump a list of py strings into go format"""
30+
return "[]string{"+",".join(string(s) for s in ss)+"}"
31+
32+
def const(x):
33+
if isinstance(x, str):
34+
return 'py.String("%s")' % x
35+
elif isinstance(x, int):
36+
return 'py.Int(%d)' % x
37+
elif isinstance(x, float):
38+
return 'py.Float(%g)' % x
39+
elif x is None:
40+
return 'py.None'
41+
else:
42+
raise AssertionError("Unknown const %r" % x)
43+
44+
def consts(xs):
45+
return "[]py.Object{"+",".join(const(x) for x in xs)+"}"
46+
47+
def _compile(source, mode):
48+
"""compile source with mode"""
49+
a = compile(source=source, filename="<string>", mode=mode, dont_inherit=True, optimize=0)
50+
return a, "\n".join([
51+
"py.Code{",
52+
"Argcount: %s," % a.co_argcount,
53+
"Kwonlyargcount: %s," % a.co_kwonlyargcount,
54+
"Nlocals: %s," % a.co_nlocals,
55+
"Stacksize: %s," % a.co_stacksize,
56+
"Flags: %s," % a.co_flags,
57+
"Code: %s," % string(a.co_code),
58+
"Consts: %s," % consts(a.co_consts),
59+
"Names: %s," % strings(a.co_names),
60+
"Varnames: %s," % strings(a.co_varnames),
61+
"Freevars: %s," % strings(a.co_freevars),
62+
"Cellvars: %s," % strings(a.co_cellvars),
63+
# "Cell2arg []byte // Maps cell vars which are arguments".
64+
"Filename: %s," % string(a.co_filename),
65+
"Name: %s," % string(a.co_name),
66+
"Firstlineno: %d," % a.co_firstlineno,
67+
"Lnotab: %s," % string(a.co_lnotab),
68+
"}",
69+
])
70+
71+
def escape(x):
72+
"""Encode strings with backslashes for python/go"""
73+
return x.replace('\\', "\\\\").replace('"', r'\"').replace("\n", r'\n').replace("\t", r'\t')
74+
75+
def main():
76+
"""Write compile_data_test.go"""
77+
path = "compile_data_test.go"
78+
out = ["""// Test data generated by make_compile_test.py - do not edit
79+
80+
package compile
81+
82+
import (
83+
"github.com/ncw/gpython/py"
84+
)
85+
86+
var compileTestData = []struct {
87+
in string
88+
mode string // exec, eval or single
89+
out py.Code
90+
dis string
91+
}{"""]
92+
for source, mode in inp:
93+
code, gostring = _compile(source, mode)
94+
discode = dis.Bytecode(code)
95+
out.append('{"%s", "%s", %s, "%s"},' % (escape(source), mode, gostring, escape(discode.dis())))
96+
out.append("}")
97+
print("Writing %s" % path)
98+
with open(path, "w") as f:
99+
f.write("\n".join(out))
100+
f.write("\n")
101+
subprocess.check_call(["gofmt", "-w", path])
102+
103+
if __name__ == "__main__":
104+
main()

0 commit comments

Comments
 (0)