Skip to content

Commit 690ec87

Browse files
Refactoring of integration tests (#685)
1 parent 5ada20b commit 690ec87

File tree

5 files changed

+967
-624
lines changed

5 files changed

+967
-624
lines changed

Makefile

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,26 +44,45 @@ integration:
4444
if [ ! -d rust_vm_bin ]; then \
4545
mkdir -p rust_vm_bin; \
4646
fi; \
47-
if [ ! -d rust_vm_bin/cairo ]; then \
48-
mkdir -p rust_vm_bin/cairo-lang; \
47+
if [ ! -d rust_vm_bin/scj/scj ]; then \
48+
mkdir -p rust_vm_bin/scj/scj; \
4949
fi; \
50-
if [ ! -f ./rust_vm_bin/cairo-lang/cairo-compile ] || [ ! -f ./rust_vm_bin/cairo-lang/sierra-compile-json ] || [ ! -d rust_vm_bin/corelib ]; then \
51-
cd rust_vm_bin; \
52-
git clone --single-branch --branch feat/main-casm-json --depth=1 https://github.com/zmalatrax/cairo.git; \
53-
mv cairo/corelib .; \
54-
cd cairo/crates/bin && cargo build --release --bin cairo-compile --bin sierra-compile-json && cd ../../../; \
55-
mv cairo/target/release/cairo-compile cairo/target/release/sierra-compile-json cairo-lang; \
56-
rm -rf cairo; \
57-
cd ../; \
50+
if [ ! -d rust_vm_bin/starkware/starkware ]; then \
51+
mkdir -p rust_vm_bin/starkware/starkware; \
5852
fi; \
59-
if [ ! -f ./rust_vm_bin/cairo-lang/cairo1-run ] || [ ! -f ./rust_vm_bin/cairo-vm-cli ]; then \
60-
cd rust_vm_bin; \
61-
git clone https://github.com/lambdaclass/cairo-vm.git; \
62-
cd cairo-vm && cargo build --release --bin cairo-vm-cli --bin cairo1-run && cd ../; \
63-
mv cairo-vm/target/release/cairo1-run cairo-lang;\
64-
mv cairo-vm/target/release/cairo-vm-cli . ; \
65-
rm -rf cairo-vm; \
66-
cd ../; \
53+
if [ ! -d rust_vm_bin/lambdaclass/lambdaclass ]; then \
54+
mkdir -p rust_vm_bin/lambdaclass/lambdaclass; \
55+
fi; \
56+
if [ ! -f ./rust_vm_bin/scj/scj/sierra-compile-json ]; then \
57+
cd rust_vm_bin/scj/scj && \
58+
git clone --single-branch --branch feat/main-casm-json --depth=1 https://github.com/zmalatrax/cairo.git && \
59+
cd cairo/crates/bin && cargo build --release --bin sierra-compile-json && \
60+
cd ../../../ && \
61+
mv cairo/target/release/sierra-compile-json . && \
62+
mv cairo/corelib ../ && \
63+
rm -rf cairo && \
64+
cd ../../../; \
65+
fi; \
66+
if [ ! -f ./rust_vm_bin/starkware/starkware/cairo-run ] || [ ! -f ./rust_vm_bin/starkware/starkware/cairo-compile ]; then \
67+
cd rust_vm_bin/starkware/starkware && \
68+
git clone https://github.com/starkware-libs/cairo.git && \
69+
mv cairo/corelib ../ && \
70+
cd cairo/crates/bin && cargo build --release --bin cairo-compile --bin cairo-run && \
71+
cd ../../../ && \
72+
mv cairo/target/release/cairo-compile cairo/target/release/cairo-run . && \
73+
rm -rf cairo && \
74+
cd ../../../; \
75+
fi; \
76+
if [ ! -f ./rust_vm_bin/lambdaclass/lambdaclass/cairo1-run ] || [ ! -f ./rust_vm_bin/lambdaclass/lambdaclass/cairo-vm-cli ]; then \
77+
cd rust_vm_bin/lambdaclass/lambdaclass && \
78+
git clone https://github.com/lambdaclass/cairo-vm.git && \
79+
cd cairo-vm/cairo1-run && make deps && \
80+
cd ../../cairo-vm && cargo build --release --bin cairo-vm-cli --bin cairo1-run && \
81+
cd ../ && \
82+
mv cairo-vm/target/release/cairo1-run cairo-vm/target/release/cairo-vm-cli . && \
83+
mv cairo-vm/cairo1-run/corelib ../ && \
84+
rm -rf cairo-vm && \
85+
cd ../../../; \
6786
fi; \
6887
go test ./integration_tests/... -v; \
6988
else \

integration_tests/cairo0_test.go

Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
package integrationtests
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"os"
7+
"os/exec"
8+
"path/filepath"
9+
"sync"
10+
"testing"
11+
"time"
12+
13+
"github.com/stretchr/testify/assert"
14+
"github.com/stretchr/testify/require"
15+
)
16+
17+
func runAndTestCairoZeroFile(t *testing.T, path string, name string, benchmarkMap map[string][]int, benchmark bool, errorExpected bool) {
18+
t.Logf("testing: %s\n", path)
19+
compiledOutput, err := compileCairoZeroCode(path)
20+
if err != nil {
21+
t.Error(err)
22+
return
23+
}
24+
layout := getLayoutFromFileName(path)
25+
26+
elapsedGo, traceFile, memoryFile, _, err := runVmZero(compiledOutput, layout)
27+
if errorExpected {
28+
assert.Error(t, err, path)
29+
writeToFile(path)
30+
return
31+
} else {
32+
if err != nil {
33+
t.Error(err)
34+
writeToFile(path)
35+
return
36+
}
37+
}
38+
39+
rustVmFilePath := compiledOutput
40+
elapsedRs, rsTraceFile, rsMemoryFile, err := runRustVmZero(rustVmFilePath, layout)
41+
if errorExpected {
42+
// we let the code go on so that we can check if the go vm also raises an error
43+
assert.Error(t, err, path)
44+
return
45+
} else {
46+
if err != nil {
47+
t.Error(err)
48+
writeToFile(path)
49+
return
50+
}
51+
}
52+
53+
trace, memory, err := decodeProof(traceFile, memoryFile)
54+
if err != nil {
55+
t.Error(err)
56+
writeToFile(path)
57+
return
58+
}
59+
rsTrace, rsMemory, err := decodeProof(rsTraceFile, rsMemoryFile)
60+
if err != nil {
61+
t.Error(err)
62+
writeToFile(path)
63+
return
64+
}
65+
66+
if !assert.Equal(t, rsTrace, trace) {
67+
t.Logf("rstrace:\n%s\n", traceRepr(rsTrace))
68+
t.Logf("trace:\n%s\n", traceRepr(trace))
69+
writeToFile(path)
70+
}
71+
if !assert.Equal(t, rsMemory, memory) {
72+
t.Logf("rsmemory;\n%s\n", memoryRepr(rsMemory))
73+
t.Logf("memory;\n%s\n", memoryRepr(memory))
74+
writeToFile(path)
75+
}
76+
77+
elapsedPy, pyTraceFile, pyMemoryFile, err := runPythonVm(compiledOutput, layout)
78+
if errorExpected {
79+
// we let the code go on so that we can check if the go vm also raises an error
80+
assert.Error(t, err, path)
81+
} else {
82+
if err != nil {
83+
t.Error(err)
84+
return
85+
}
86+
}
87+
88+
if benchmark {
89+
benchmarkMap[name] = []int{int(elapsedPy.Milliseconds()), int(elapsedGo.Milliseconds()), int(elapsedRs.Milliseconds())}
90+
}
91+
92+
pyTrace, pyMemory, err := decodeProof(pyTraceFile, pyMemoryFile)
93+
if err != nil {
94+
t.Error(err)
95+
return
96+
}
97+
98+
if !assert.Equal(t, pyTrace, trace) {
99+
t.Logf("pytrace:\n%s\n", traceRepr(pyTrace))
100+
t.Logf("trace:\n%s\n", traceRepr(trace))
101+
writeToFile(path)
102+
}
103+
if !assert.Equal(t, pyMemory, memory) {
104+
t.Logf("pymemory;\n%s\n", memoryRepr(pyMemory))
105+
t.Logf("memory;\n%s\n", memoryRepr(memory))
106+
writeToFile(path)
107+
}
108+
}
109+
110+
var zerobench = flag.Bool("zerobench", false, "run integration tests and generate benchmarks file")
111+
112+
func TestCairoZeroFiles(t *testing.T) {
113+
file, err := os.OpenFile(whitelistFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
114+
if err != nil {
115+
panic(fmt.Errorf("failed to open file: %w", err))
116+
}
117+
118+
file.Close()
119+
120+
roots := []string{
121+
"./cairo_zero_hint_tests/",
122+
"./cairo_zero_file_tests/",
123+
"./builtin_tests/",
124+
}
125+
126+
// filter is for debugging purposes
127+
filter := Filter{}
128+
filter.init()
129+
130+
benchmarkMap := make(map[string][]int)
131+
132+
sem := make(chan struct{}, 5) // semaphore to limit concurrency
133+
var wg sync.WaitGroup // WaitGroup to wait for all goroutines to finish
134+
135+
for _, root := range roots {
136+
testFiles, err := os.ReadDir(root)
137+
require.NoError(t, err)
138+
139+
for _, dirEntry := range testFiles {
140+
if dirEntry.IsDir() || isGeneratedFile(dirEntry.Name()) {
141+
continue
142+
}
143+
144+
name := dirEntry.Name()
145+
path := filepath.Join(root, name)
146+
147+
errorExpected := false
148+
if name == "range_check__small.cairo" {
149+
errorExpected = true
150+
}
151+
if !filter.filtered(name) {
152+
continue
153+
}
154+
// we run tests concurrently if we don't need benchmarks
155+
if !*zerobench {
156+
sem <- struct{}{} // acquire a semaphore slot
157+
wg.Add(1)
158+
159+
go func(path, name string) {
160+
defer wg.Done()
161+
defer func() { <-sem }() // release the semaphore slot when done
162+
runAndTestCairoZeroFile(t, path, name, benchmarkMap, *zerobench, errorExpected)
163+
}(path, name)
164+
} else {
165+
runAndTestCairoZeroFile(t, path, name, benchmarkMap, *zerobench, errorExpected)
166+
}
167+
}
168+
}
169+
170+
wg.Wait() // wait for all goroutines to finish
171+
172+
for _, root := range roots {
173+
clean(root)
174+
}
175+
176+
if *zerobench {
177+
WriteBenchMarksToFile(benchmarkMap)
178+
}
179+
}
180+
181+
// given a path to a cairo zero file, it compiles it
182+
// and return the compilation path
183+
func compileCairoZeroCode(path string) (string, error) {
184+
if filepath.Ext(path) != ".cairo" {
185+
return "", fmt.Errorf("compiling non cairo file: %s", path)
186+
}
187+
compiledOutput := swapExtenstion(path, compiledSuffix)
188+
189+
var cliCommand string
190+
var args []string
191+
192+
cliCommand = "cairo-compile"
193+
args = []string{
194+
path,
195+
"--proof_mode",
196+
"--no_debug_info",
197+
"--output",
198+
compiledOutput,
199+
}
200+
cmd := exec.Command(cliCommand, args...)
201+
202+
res, err := cmd.CombinedOutput()
203+
if err != nil {
204+
return "", fmt.Errorf(
205+
"%s %s: %w\n%s", cliCommand, path, err, string(res),
206+
)
207+
}
208+
209+
return compiledOutput, nil
210+
}
211+
212+
// given a path to a compiled cairo zero file, execute it using the
213+
// python vm and returns the trace and memory files location
214+
func runPythonVm(path, layout string) (time.Duration, string, string, error) {
215+
traceOutput := swapExtenstion(path, pyTraceSuffix)
216+
memoryOutput := swapExtenstion(path, pyMemorySuffix)
217+
218+
args := []string{
219+
"--program",
220+
path,
221+
"--proof_mode",
222+
"--trace_file",
223+
traceOutput,
224+
"--memory_file",
225+
memoryOutput,
226+
"--layout",
227+
layout,
228+
}
229+
230+
cmd := exec.Command("cairo-run", args...)
231+
232+
start := time.Now()
233+
234+
res, err := cmd.CombinedOutput()
235+
236+
elapsed := time.Since(start)
237+
238+
if err != nil {
239+
return 0, "", "", fmt.Errorf(
240+
"cairo-run %s: %w\n%s", path, err, string(res),
241+
)
242+
}
243+
244+
return elapsed, traceOutput, memoryOutput, nil
245+
}
246+
247+
// given a path to a compiled cairo zero file, execute it using the
248+
// rust vm and return the trace and memory files location
249+
func runRustVmZero(path, layout string) (time.Duration, string, string, error) {
250+
traceOutput := swapExtenstion(path, rsTraceSuffix)
251+
memoryOutput := swapExtenstion(path, rsMemorySuffix)
252+
253+
args := []string{
254+
path,
255+
"--trace_file",
256+
traceOutput,
257+
"--memory_file",
258+
memoryOutput,
259+
"--layout",
260+
layout,
261+
"--proof_mode",
262+
}
263+
264+
binaryPath := "./../rust_vm_bin/lambdaclass/lambdaclass/cairo-vm-cli"
265+
266+
cmd := exec.Command(binaryPath, args...)
267+
268+
start := time.Now()
269+
270+
res, err := cmd.CombinedOutput()
271+
272+
elapsed := time.Since(start)
273+
274+
if err != nil {
275+
return 0, "", "", fmt.Errorf(
276+
"%s %s: %w\n%s", binaryPath, path, err, string(res),
277+
)
278+
}
279+
280+
return elapsed, traceOutput, memoryOutput, nil
281+
}
282+
283+
// given a path to a compiled cairo zero file, execute
284+
// it using our vm
285+
func runVmZero(path, layout string) (time.Duration, string, string, string, error) {
286+
traceOutput := swapExtenstion(path, traceSuffix)
287+
memoryOutput := swapExtenstion(path, memorySuffix)
288+
289+
args := []string{
290+
"run",
291+
"--proofmode",
292+
"--tracefile",
293+
traceOutput,
294+
"--memoryfile",
295+
memoryOutput,
296+
"--layout",
297+
layout,
298+
}
299+
args = append(args, path)
300+
cmd := exec.Command(
301+
"../bin/cairo-vm",
302+
args...,
303+
)
304+
305+
start := time.Now()
306+
307+
res, err := cmd.CombinedOutput()
308+
309+
elapsed := time.Since(start)
310+
311+
if err != nil {
312+
return 0, "", "", string(res), fmt.Errorf(
313+
"cairo-vm run %s: %w\n%s", path, err, string(res),
314+
)
315+
}
316+
317+
return elapsed, traceOutput, memoryOutput, string(res), nil
318+
}

0 commit comments

Comments
 (0)