github.com/smasher164/tapl@v0.0.0-20230202055446-fd56bc413abd/tests/arith/all_test.go (about) 1 package arith_test 2 3 import ( 4 "bytes" 5 "io/fs" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "strings" 10 "testing" 11 ) 12 13 var ( 14 testPath = func() string { 15 cwd, err := os.Getwd() 16 panicErr(err) 17 return cwd 18 }() 19 projectRoot = filepath.Dir(filepath.Dir(testPath)) 20 testDir = os.DirFS(testPath) 21 inOut = func() map[string]string { 22 m := make(map[string]string) 23 panicErr(fs.WalkDir(testDir, ".", func(path string, d fs.DirEntry, err error) error { 24 parts := strings.Split(path, ".") 25 if len(parts) == 3 && parts[1] == "in" { 26 m[filepath.Join(testPath, path)] = strings.Join([]string{parts[0], "out.txt"}, ".") 27 } 28 return err 29 })) 30 return m 31 }() 32 ) 33 34 func panicErr(err error) { 35 if err != nil { 36 panic(err) 37 } 38 } 39 40 func test(name string, args ...string) func(t *testing.T) { 41 return func(t *testing.T) { 42 for in, out := range inOut { 43 got, err := exec.Command(name, append(args, in)...).CombinedOutput() 44 if _, ok := err.(*exec.ExitError); !ok && err != nil { 45 t.Fatal(err) 46 } 47 want, err := fs.ReadFile(testDir, out) 48 if err != nil { 49 t.Fatal(err) 50 } 51 if bytes.Compare(got, want) != 0 { 52 t.Errorf("%s does not match output:\n`%s`", out, got) 53 } 54 } 55 } 56 } 57 58 func run(name string, args ...string) error { 59 cmd := exec.Command(name, args...) 60 cmd.Stderr = os.Stderr 61 return cmd.Run() 62 } 63 64 func TestGo(t *testing.T) { 65 if _, err := exec.LookPath("go"); err != nil { 66 t.Skip("could not find 'go' executable in PATH") 67 } 68 goDir := filepath.Join(projectRoot, "go", "arith") 69 os.Chdir(goDir) 70 if err := run("go", "build"); err != nil { 71 t.Fatal(err) 72 } 73 t.Run("SmallStep", test("./arith", "-small-step")) 74 t.Run("BigStep", test("./arith", "-big-step")) 75 } 76 77 func TestSML(t *testing.T) { 78 if _, err := exec.LookPath("mlton"); err != nil { 79 t.Skip("could not find 'mlton' executable in PATH") 80 } 81 smlDir := filepath.Join(projectRoot, "sml", "arith") 82 os.Chdir(smlDir) 83 if err := run( 84 "mlton", 85 "-default-ann", "allowExtendedTextConsts true", 86 "-default-ann", "allowOrPats true", 87 "arith.sml", 88 ); err != nil { 89 t.Fatal(err) 90 } 91 t.Run("SmallStep", test("./arith", "-small-step")) 92 t.Run("BigStep", test("./arith", "-big-step")) 93 } 94 95 func TestC(t *testing.T) { 96 if _, err := exec.LookPath("cc"); err == nil { 97 cDir := filepath.Join(projectRoot, "c", "arith") 98 os.Chdir(cDir) 99 if err := run("cc", "-o", "arith", "arith.c"); err != nil { 100 t.Fatal(err) 101 } 102 } else if _, err := exec.LookPath("cl"); err == nil { 103 cDir := filepath.Join(projectRoot, "c", "arith") 104 os.Chdir(cDir) 105 if err := run("cl", "/std:c11", "/Fearith", "arith.c"); err != nil { 106 t.Fatal(err) 107 } 108 } else { 109 t.Skip("could not find 'cc' or 'cl' in PATH") 110 } 111 t.Run("SmallStep", test("./arith", "-small-step")) 112 t.Run("BigStep", test("./arith", "-big-step")) 113 } 114 115 func TestRust(t *testing.T) { 116 if _, err := exec.LookPath("cargo"); err != nil { 117 t.Skip("could not find 'cargo' executable in PATH") 118 } 119 rustDir := filepath.Join(projectRoot, "rust") 120 os.Chdir(rustDir) 121 if err := run("cargo", "build", "--quiet", "--release", "-p", "arith"); err != nil { 122 t.Fatal(err) 123 } 124 t.Run("SmallStep", test("./target/release/arith", "-small-step")) 125 t.Run("BigStep", test("./target/release/arith", "-big-step")) 126 } 127 128 func TestRaku(t *testing.T) { 129 if _, err := exec.LookPath("raku"); err != nil { 130 t.Skip("could not find 'raku' executable in PATH") 131 } 132 rakuDir := filepath.Join(projectRoot, "raku", "arith") 133 os.Chdir(rakuDir) 134 t.Run("SmallStep", test("raku", "arith.raku", "-small-step")) 135 t.Run("BigStep", test("raku", "arith.raku", "-big-step")) 136 }