1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
package main
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
var nexBin string
func init() {
var err error
if nexBin, err = filepath.Abs(os.Getenv("GOPATH") + "/bin/nex"); err != nil {
panic(err)
}
if _, err := os.Stat(nexBin); err != nil {
if nexBin, err = filepath.Abs("../nex"); err != nil {
panic(err)
}
if _, err := os.Stat(nexBin); err != nil {
panic("cannot find nex binary")
}
}
}
func dieErr(t *testing.T, err error, s string) {
if err != nil {
t.Fatalf("%s: %s", s, err)
}
}
func TestWax(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "nex")
dieErr(t, err, "TempDir")
defer func() {
dieErr(t, os.RemoveAll(tmpdir), "RemoveAll")
}()
run := func(s string) {
v := strings.Split(s, " ")
err := exec.Command(v[0], v[1:]...).Run()
dieErr(t, err, s)
}
run("cp tacky.nex tacky.y tacky.go build.sh " + tmpdir)
wd, err := os.Getwd()
dieErr(t, err, "Getwd")
dieErr(t, os.Chdir(tmpdir), "Chdir")
defer func() {
dieErr(t, os.Chdir(wd), "Chdir")
}()
dieErr(t, os.Setenv("NEXBIN", nexBin), "Setenv")
run("./build.sh")
cmd := exec.Command("./tacky")
cmd.Stdin = strings.NewReader(`
ID10T {
7 salary = $50000 // Initech salary.
8a disinterest = // Right-hand side of assignment can span multiple lines.
$0.01 // Additions are implicit.
$0.22
$3.33
21 other income = $305326.13 // Salami slicing.
22 total income = 7 8a 21
40 deduction = [ID10T, TPS Worksheet:10] // Line from another form.
43 taxable income = 22 - 40
44 tax = $123.45 + 43 * 33% - $678.90 // Test precedence, percentages.
99 = $99.50
100 = $100.00
101 = $100.49
}
ID10T, TPS Worksheet {
1 bank error = [ID10T:21]
// Divide by $2500 and round up.
// Looks wacky because all computations are in cents, but it works.
// However, in whole dollar mode, any rounding is likely undesirable.
2bad = (1 + $2500.00 - $0.01) / $2500.00
// The following is an example of a formula that is wrongly computed in
// whole dollar mode.
2badwrongifrounded = 1 * 2bad * 0.2%
// The right way: multiply before potential whole dollar rounding.
2 = 1 * ((1 + $2500.00 - $0.01) / $2500.00) * 0.2% // Fractional percentage.
// The line '0' is reserved. It always means $0.
3 = clip(0 - $5) // This should be 0.
4 = clip($5 - 0) // This should be $5.
5 = max(3, 4)
6 = min(5, 2)
10 = 6
}
// Test rounding to dollars.
whole_dollars_only = 1
27B-6 {
99 = [ID10T:99]
100 = [ID10T:100]
101 = [ID10T:101]
}
`)
want := `ID10T
7 salary $50000.00
8a disinterest $3.56
21 other income $305326.13
22 total income $355329.69
40 deduction $5.00
43 taxable income $355324.69
44 tax $116701.70
99 $99.50
100 $100.00
101 $100.49
ID10T, TPS Worksheet
1 bank error $305326.13
2bad $1.23
2badwrongifrounded $75110.23
2 $75110.23
3 $0.00
4 $5.00
5 $5.00
6 $5.00
10 $5.00
27B-6
99 $100.00
100 $100.00
101 $100.00
`
got, err := cmd.CombinedOutput()
dieErr(t, err, "CombinedOutput")
if want != string(got) {
t.Fatalf("want %q, got %q", want, string(got))
}
}
|