github.com/vugu/vugu@v0.3.5/gen/parser-go-pkg_test.go (about) 1 package gen 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "regexp" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 ) 14 15 func TestSimpleParseGoPkgRun(t *testing.T) { 16 17 assert := assert.New(t) 18 19 tmpDir, err := ioutil.TempDir("", "TestParseGoPkgRun") 20 if err != nil { 21 t.Fatal(err) 22 } 23 defer os.RemoveAll(tmpDir) 24 25 // assert.NoError(ioutil.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte(` 26 // module main 27 // `), 0644)) 28 29 assert.NoError(ioutil.WriteFile(filepath.Join(tmpDir, "root.vugu"), []byte(` 30 <div id="root_comp"> 31 <h1>Hello!</h1> 32 </div> 33 `), 0644)) 34 35 p := NewParserGoPkg(tmpDir, nil) 36 37 assert.NoError(p.Run()) 38 39 b, err := ioutil.ReadFile(filepath.Join(tmpDir, "root_vgen.go")) 40 assert.NoError(err) 41 // t.Logf("OUT FILE root_vgen.go: %s", b) 42 // log.Printf("OUT FILE root_vgen.go: %s", b) 43 44 if !bytes.Contains(b, []byte(`func (c *Root) Build`)) { 45 t.Errorf("failed to find Build method signature") 46 } 47 48 b, err = ioutil.ReadFile(filepath.Join(tmpDir, "0_missing_vgen.go")) 49 assert.NoError(err) 50 51 if !bytes.Contains(b, []byte(`type Root struct`)) { 52 t.Errorf("failed to find Root struct definition") 53 } 54 55 } 56 57 func TestRun(t *testing.T) { 58 59 debug := false 60 61 pwd, err := filepath.Abs("..") 62 if err != nil { 63 t.Fatal(err) 64 } 65 66 type tcase struct { 67 name string 68 opts ParserGoPkgOpts 69 recursive bool 70 infiles map[string]string // file structure to start with 71 out map[string][]string // regexps to match in output files 72 afterRun func(dir string, t *testing.T) // called after Run 73 bfiles map[string]string // additional files to write before building 74 build string // "wasm", "default", "none" 75 } 76 77 tcList := []tcase{ 78 { 79 name: "simple", 80 opts: ParserGoPkgOpts{}, 81 recursive: false, 82 infiles: map[string]string{ 83 "root.vugu": `<div>root here</div>`, 84 "go.mod": "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n", 85 "main.go": "package main\nfunc main(){}", 86 }, 87 out: map[string][]string{ 88 "root_vgen.go": {`func \(c \*Root\) Build`}, 89 "0_missing_vgen.go": {`type Root struct`}, 90 }, 91 build: "default", 92 }, 93 { 94 name: "simple-wasm", 95 opts: ParserGoPkgOpts{}, 96 recursive: false, 97 infiles: map[string]string{ 98 "root.vugu": `<div>root here</div>`, 99 "go.mod": "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n", 100 }, 101 out: map[string][]string{ 102 "root_vgen.go": {`func \(c \*Root\) Build`}, 103 "0_missing_vgen.go": {`type Root struct`}, 104 }, 105 build: "wasm", 106 }, 107 { 108 name: "recursive", 109 opts: ParserGoPkgOpts{}, 110 recursive: true, 111 infiles: map[string]string{ 112 "root.vugu": `<div>root here</div>`, 113 "go.mod": "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n", 114 "main.go": "package main\nfunc main(){}", 115 "subdir1/example.vugu": "<div>Example Here</div>", 116 }, 117 out: map[string][]string{ 118 "root_vgen.go": {`func \(c \*Root\) Build`, `root here`}, 119 "0_missing_vgen.go": {`type Root struct`}, 120 "subdir1/example_vgen.go": {`Example Here`}, 121 }, 122 build: "default", 123 }, 124 { 125 name: "recursive-single", 126 opts: ParserGoPkgOpts{MergeSingle: true}, 127 recursive: true, 128 infiles: map[string]string{ 129 "root.vugu": `<div>root here</div>`, 130 "go.mod": "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n", 131 "main.go": "package main\nfunc main(){}", 132 "subdir1/example.vugu": "<div>Example Here</div>", 133 }, 134 out: map[string][]string{ 135 "0_components_vgen.go": {`func \(c \*Root\) Build`, `type Root struct`}, 136 "subdir1/0_components_vgen.go": {`Example Here`}, 137 "root.vugu": {`root here`}, // make sure vugu files didn't get nuked 138 "subdir1/example.vugu": {`Example Here`}, 139 }, 140 afterRun: func(dir string, t *testing.T) { 141 noFile(filepath.Join(dir, "subdir1/example_vgen.go"), t) 142 }, 143 build: "default", 144 }, 145 { 146 name: "events", 147 opts: ParserGoPkgOpts{}, 148 recursive: false, 149 infiles: map[string]string{ 150 "root.vugu": `<div>root here</div>`, 151 "go.mod": "module testcase\nreplace github.com/vugu/vugu => " + pwd + "\n", 152 "main.go": "package main\nfunc main(){}\n\n//vugugen:event Sample\n", 153 }, 154 out: map[string][]string{ 155 "root_vgen.go": {`func \(c \*Root\) Build`}, 156 "0_missing_vgen.go": {`type Root struct`, `SampleEvent`, `SampleHandler`, `SampleFunc`}, 157 }, 158 build: "default", 159 }, 160 } 161 162 for _, tc := range tcList { 163 tc := tc 164 t.Run(tc.name, func(t *testing.T) { 165 166 tmpDir, err := ioutil.TempDir("", "TestRun") 167 if err != nil { 168 t.Fatal(err) 169 } 170 171 if debug { 172 t.Logf("Test %q using tmpDir: %s", tc.name, tmpDir) 173 } else { 174 t.Parallel() 175 } 176 177 tstWriteFiles(tmpDir, tc.infiles) 178 179 if tc.recursive { 180 err = RunRecursive(tmpDir, &tc.opts) 181 } else { 182 err = Run(tmpDir, &tc.opts) 183 } 184 if err != nil { 185 t.Fatal(err) 186 } 187 188 for fname, patterns := range tc.out { 189 b, err := ioutil.ReadFile(filepath.Join(tmpDir, fname)) 190 if err != nil { 191 t.Errorf("failed to read file %q after Run: %v", fname, err) 192 continue 193 } 194 for _, pattern := range patterns { 195 re := regexp.MustCompile(pattern) 196 if !re.Match(b) { 197 t.Errorf("failed to match regexp on file %q: %s", fname, pattern) 198 } 199 } 200 } 201 202 if tc.afterRun != nil { 203 tc.afterRun(tmpDir, t) 204 } 205 206 tstWriteFiles(tmpDir, tc.bfiles) 207 208 cmd := exec.Command("go", "mod", "tidy") 209 cmd.Dir = tmpDir 210 b, err := cmd.CombinedOutput() 211 if err != nil { 212 t.Fatalf("go mod tidy error: %s; OUTPUT:\n%s", err, b) 213 } 214 215 switch tc.build { 216 217 case "wasm": 218 cmd := exec.Command("go", "build", "-o", "main.wasm", ".") 219 cmd.Dir = tmpDir 220 cmd.Env = os.Environ() // needed? 221 cmd.Env = append(cmd.Env, "GOOS=js", "GOARCH=wasm") 222 b, err := cmd.CombinedOutput() 223 if err != nil { 224 t.Fatalf("build error: %s; OUTPUT:\n%s", err, b) 225 } 226 227 case "default": 228 cmd := exec.Command("go", "build", "-o", "main.out", ".") 229 cmd.Dir = tmpDir 230 b, err := cmd.CombinedOutput() 231 if err != nil { 232 t.Fatalf("build error: %s; OUTPUT:\n%s", err, b) 233 } 234 235 cmd = exec.Command(filepath.Join(tmpDir, "main.out")) 236 cmd.Dir = tmpDir 237 b, err = cmd.CombinedOutput() 238 if err != nil { 239 t.Fatalf("run error: %s; OUTPUT:\n%s", err, b) 240 } 241 242 case "none": 243 244 default: 245 t.Errorf("unknown build value %q", tc.build) 246 } 247 248 // only if everthing is golden do we remove 249 if !t.Failed() { 250 os.RemoveAll(tmpDir) 251 } 252 253 }) 254 } 255 256 } 257 258 func noFile(p string, t *testing.T) { 259 _, err := os.Stat(p) 260 if err == nil { 261 t.Errorf("file %q should not exist but does", p) 262 } 263 } 264 265 func tstWriteFiles(dir string, m map[string]string) { 266 267 for name, contents := range m { 268 p := filepath.Join(dir, name) 269 os.MkdirAll(filepath.Dir(p), 0755) 270 err := ioutil.WriteFile(p, []byte(contents), 0644) 271 if err != nil { 272 panic(err) 273 } 274 } 275 276 }