github.com/vugu/vugu@v0.3.6-0.20240430171613-3f6f402e014b/gen/missing-fixer_test.go (about) 1 package gen 2 3 import ( 4 "os" 5 "os/exec" 6 "path/filepath" 7 "runtime" 8 "strings" 9 "testing" 10 ) 11 12 func TestMissingFixer(t *testing.T) { 13 14 // NOTE: for more complex testing, see TestRun which is easier to add more general cases to. 15 16 tmpDir, err := os.MkdirTemp("", "TestMissingFixer") 17 if err != nil { 18 t.Fatal(err) 19 } 20 defer os.RemoveAll(tmpDir) 21 22 must := func(err error) { 23 if err != nil { 24 _, file, line, _ := runtime.Caller(1) 25 t.Fatalf("from %s:%d: %v", file, line, err) 26 } 27 } 28 vuguAbs, _ := filepath.Abs("..") 29 30 must(os.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte("module missingfixertest\n\nreplace github.com/vugu/vugu => "+vuguAbs+"\n"), 0644)) 31 must(os.WriteFile(filepath.Join(tmpDir, "events.go"), []byte("package main\n\n//vugugen:event Something\n//vugugen:event SomeOtherThing\n//vugugen:event SomeOtherThing\n"), 0644)) 32 must(os.WriteFile(filepath.Join(tmpDir, "root.vugu"), []byte("<div>root</div>"), 0644)) 33 must(os.WriteFile(filepath.Join(tmpDir, "root_gen.go"), []byte("package main\n\nimport \"github.com/vugu/vugu\"\n\nfunc (c *Root)Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {return nil}"), 0644)) 34 // a second component that does include it's own struct definition 35 must(os.WriteFile(filepath.Join(tmpDir, "comp1.vugu"), []byte("<div>comp1</div>"), 0644)) 36 must(os.WriteFile(filepath.Join(tmpDir, "comp1_gen.go"), []byte("package main\n\nimport \"github.com/vugu/vugu\"\n\ntype Comp1 struct{}\n\nfunc (c *Comp1)Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {return nil}"), 0644)) 37 // a file with an event where the event type is declared but not the handler interface or func 38 must(os.WriteFile(filepath.Join(tmpDir, "epart.go"), []byte("package main\n\n//vugugen:event Part\ntype PartEvent struct { A string }\n"), 0644)) 39 40 // // TEMP 41 // must(os.WriteFile(filepath.Join(tmpDir, "root_gen.go"), []byte(` 42 // package main 43 44 // import "github.com/vugu/vugu" 45 46 // type Root struct {} 47 48 // func (c *Root)Build(vgin *vugu.BuildIn) (vgout *vugu.BuildOut) {return nil} 49 50 // `), 0644)) 51 52 mf := newMissingFixer(tmpDir, "main", map[string]string{ 53 "root.vugu": "root_gen.go", 54 // "comp1.vugu": "comp1_gen.go", 55 }) 56 err = mf.run() 57 if err != nil { 58 t.Fatal(err) 59 } 60 61 b, err := os.ReadFile(filepath.Join(tmpDir, "0_missing_gen.go")) 62 must(err) 63 t.Logf("0_missing_gen.go result:\n%s", b) 64 s := string(b) 65 checks := []string{ 66 "type Root struct", 67 68 "!type Comp1 struct", 69 70 "type SomethingEvent struct", 71 "type SomethingHandler interface", 72 "type SomethingFunc func", 73 "func (f SomethingFunc) SomethingHandle(", 74 "var _ SomethingHandler =", 75 76 // "type PartEvent struct", // should exist only in epart.go 77 78 // "type SomeOtherThingEvent interface", 79 // "type SomeOtherThingHandler interface", 80 // "type SomeOtherThingHandlerFunc func", 81 // "func (f SomeOtherThingHandlerFunc) SomeOtherThingHandle(", 82 // "var _ SomeOtherThingHandler =", 83 } 84 for _, check := range checks { 85 if check[0] == '!' { 86 if strings.Contains(s, check[1:]) { 87 t.Errorf("found unexpected %q", check[1:]) 88 } 89 } else if !strings.Contains(s, check) { 90 t.Errorf("missing %q", check) 91 } 92 } 93 94 if t.Failed() { 95 return 96 } 97 // if the above worked, try compiling it 98 must(os.WriteFile(filepath.Join(tmpDir, "main.go"), []byte("package main\n\nfunc main(){}\n"), 0644)) 99 100 cmd := exec.Command("go", "mod", "tidy") 101 cmd.Dir = tmpDir 102 _, err = cmd.CombinedOutput() 103 if err != nil { 104 t.Logf("build output: %s", b) 105 t.Fatal(err) 106 } 107 cmd = exec.Command("go", "build", "-o", "a.out", ".") 108 cmd.Dir = tmpDir 109 b, err = cmd.CombinedOutput() 110 if err != nil { 111 t.Logf("build output: %s", b) 112 t.Fatal(err) 113 } 114 115 // ensure the output is there 116 _, err = os.Stat(filepath.Join(tmpDir, "a.out")) 117 if err != nil { 118 t.Fatal(err) 119 } 120 }