tacky_test.go 3.0 KB

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