diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 250ab1a..25fbbfd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,3 +21,9 @@ jobs: - name: Build run: go build ./... working-directory: raylib + - name: Install gocovmerge + run: go install github.com/wadey/gocovmerge@latest + working-directory: . + - name: Coverage without view the results + run: go run coverage.go + working-directory: . diff --git a/.gitignore b/.gitignore index 824d669..70ddd37 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ # Ignore go.sum when go.mod is added. go.sum +**/coverage_test.go +**/*.coverage diff --git a/coverage.go b/coverage.go new file mode 100644 index 0000000..fdd6df1 --- /dev/null +++ b/coverage.go @@ -0,0 +1,200 @@ +package main + +import ( + "errors" + "flag" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" +) + +const ( + exitName = "exit_key" + coverage_test = ` +package main + +import ( + "testing" + "time" +) + +func Test(t *testing.T) { + go func() { + time.Sleep(time.Second) + exit_key = true + }() + main() +}` +) + +// coverage packages +var coverpkgs = [...]string{ + "github.com/gen2brain/raylib-go/raylib", + "github.com/gen2brain/raylib-go/raygui", +} + +func main() { + // only for linux + switch runtime.GOOS { + case "linux", "darwin": + // do nothing + default: + log.Println("not supported OS") + return + } + + view := flag.Bool("v", false, "view html result of coverage test") + flag.Parse() + + // test of test + if !strings.Contains(coverage_test, exitName) { + log.Fatalln("source of main_test have not name: ", exitName) + return + } + + // create templorary folder + tempDir, err := os.MkdirTemp("", "coverage") + if err != nil { + log.Fatal(err) + return + } + log.Println("Prepare test folder: ", tempDir) + + // do not delete templorary folder + // defer os.Remove(tempDir.Name()) + + // // copy example folder + // log.Println("copy `examples` folder") + // if _, err := exec.Command("cp", "-r", "./examples/", tempDir).Output(); err != nil { + // log.Fatalf("%v", err) + // return + // } + + // walking + log.Println("walking by temp folder with `main.go` files") + var testPaths []string + if err := filepath.Walk("./examples/", + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !strings.HasSuffix(path, "main.go") { + return nil + } + index := strings.LastIndex(path, "/") + testPaths = append(testPaths, path[:index]) + return nil + }); err != nil { + log.Fatalf("%v", err) + return + } + + // TODO: create test in parallel + for index, testPath := range testPaths { + if 0 < flag.NArg() && !strings.Contains(testPath, os.Args[len(os.Args)-1]) { + continue + } + if err := coverage(index, testPath, tempDir); err != nil { + log.Fatalf("%v", err) + return + } + } + + // combine coverage files + log.Println("combine coverage files") + var combineFiles []string + combineName := "all.coverage" + if err := filepath.Walk(tempDir, + func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if info.IsDir() { + return nil + } + combineFiles = append(combineFiles, path) + fmt.Println(path) + return nil + }); err != nil { + log.Fatalf("%v", err) + return + } + cmd := exec.Command("gocovmerge", combineFiles...) + cmd.Dir = "./raygui/" + var out []byte + out, err = cmd.Output() + if err != nil { + log.Fatalf("gocovmerge: %v", err) + return + } + if err = os.WriteFile("./raygui/"+combineName, []byte(out), 0644); err != nil { + log.Fatalf("writefile: %v", err) + return + } + + // run coverage + if *view { + log.Println("run coverage") + cmd = exec.Command( + "go", "tool", "cover", + "-html="+combineName, + ) + cmd.Dir = "./raygui/" + if _, err = cmd.Output(); err != nil { + log.Fatalf("%v", err) + return + } + } +} + +func coverage(index int, testPath, coverPath string) (err error) { + name := strings.ReplaceAll(testPath, coverPath, "") + log.Printf("run: %s", name) + + // has file main.go + if _, err = os.Stat(testPath + "/main.go"); errors.Is(err, os.ErrNotExist) { + log.Printf("file `main.go` not exist") + return + } + + // has exitName + { + var dat []byte + dat, err = os.ReadFile(testPath + "/main.go") + if err != nil { + log.Fatalf("readfile: %v", err) + return + } + if !strings.Contains(string(dat), exitName) { + log.Printf("file `main.go` have not `%s`", exitName) + return + } + } + + // create main_test file + log.Println("create `main_test.go` file") + if err = os.WriteFile(testPath+"/coverage_test.go", []byte(coverage_test), 0644); err != nil { + log.Fatalf("writefile: %v", err) + return + } + + // testing + log.Println("testing") + for ic, cpkg := range coverpkgs { + cmd := exec.Command( + "go", "test", + fmt.Sprintf("-coverprofile=%s/%d.%d.coverage", coverPath, index, ic), + fmt.Sprintf("-coverpkg=%s", cpkg), + ) + cmd.Dir = testPath + if _, err = cmd.Output(); err != nil { + log.Fatalf("%v", err) + return + } + } + return +} diff --git a/examples/gui/basic_controls/main.go b/examples/gui/basic_controls/main.go index b51838f..ff8fad8 100644 --- a/examples/gui/basic_controls/main.go +++ b/examples/gui/basic_controls/main.go @@ -8,6 +8,8 @@ import ( rl "github.com/gen2brain/raylib-go/raylib" ) +var exit_key = false + func main() { screenWidth := int32(800) screenHeight := int32(450) @@ -38,7 +40,7 @@ func main() { rl.SetTargetFPS(60) - for !rl.WindowShouldClose() { + for !(rl.WindowShouldClose() || exit_key) { if buttonClicked { progressValue += 0.1 if progressValue >= 1.1 { diff --git a/examples/gui/button/go.mod b/examples/gui/button/go.mod index 7ce5cb7..2d205c1 100644 --- a/examples/gui/button/go.mod +++ b/examples/gui/button/go.mod @@ -6,3 +6,6 @@ require ( github.com/gen2brain/raylib-go/raygui v0.0.0-20221117130019-ce3c8e83dd6d github.com/gen2brain/raylib-go/raylib v0.0.0-20221117130019-ce3c8e83dd6d ) + +replace github.com/gen2brain/raylib-go/raylib => ../../../raylib +replace github.com/gen2brain/raylib-go/raygui => ../../../raygui diff --git a/examples/gui/button/main.go b/examples/gui/button/main.go index c7b3a12..0823295 100644 --- a/examples/gui/button/main.go +++ b/examples/gui/button/main.go @@ -3,10 +3,12 @@ package main import ( "fmt" - rl "github.com/gen2brain/raylib-go/raylib" - gui "github.com/gen2brain/raylib-go/raygui" + gui "github.com/gen2brain/raylib-go/raygui" + rl "github.com/gen2brain/raylib-go/raylib" ) +var exit_key = false + func main() { rl.InitWindow(800, 450, "raygui - button") @@ -14,7 +16,7 @@ func main() { var button bool - for !rl.WindowShouldClose() { + for !(rl.WindowShouldClose() || exit_key) { rl.BeginDrawing() rl.ClearBackground(rl.Black) diff --git a/examples/gui/controls_test_suite/controls_test_suite.go b/examples/gui/controls_test_suite/main.go similarity index 98% rename from examples/gui/controls_test_suite/controls_test_suite.go rename to examples/gui/controls_test_suite/main.go index 1cad647..80d2a60 100644 --- a/examples/gui/controls_test_suite/controls_test_suite.go +++ b/examples/gui/controls_test_suite/main.go @@ -7,6 +7,8 @@ import ( rl "github.com/gen2brain/raylib-go/raylib" ) +var exit_key = false + /******************************************************************************************* * * raygui - controls test suite @@ -123,7 +125,7 @@ func main() { //-------------------------------------------------------------------------------------- // Main game loop - for !exitWindow { // Detect window close button or ESC key + for !(exitWindow || exit_key) { // Detect window close button or ESC key // Update //---------------------------------------------------------------------------------- exitWindow = rl.WindowShouldClose() @@ -228,7 +230,7 @@ func main() { sliderValue = gui.Slider(rl.Rectangle{355, 400, 165, 20}, "TEST", fmt.Sprintf("%2.2f", sliderValue), sliderValue, -50, 100) sliderBarValue = gui.SliderBar(rl.Rectangle{320, 430, 200, 20}, "", - fmt.Sprint("%d", sliderBarValue), sliderBarValue, 0, 100) + fmt.Sprintf("%2.2f", sliderBarValue), sliderBarValue, 0, 100) progressValue = gui.ProgressBar(rl.Rectangle{320, 460, 200, 20}, "", "", progressValue, 0, 1) // NOTE: View rectangle could be used to perform some scissor test diff --git a/examples/gui/portable_window/portable_window.go b/examples/gui/portable_window/main.go similarity index 96% rename from examples/gui/portable_window/portable_window.go rename to examples/gui/portable_window/main.go index 2e4754b..aaa8efd 100644 --- a/examples/gui/portable_window/portable_window.go +++ b/examples/gui/portable_window/main.go @@ -24,6 +24,8 @@ import ( * **********************************************************************************************/ +var exit_key = false + //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ @@ -54,7 +56,7 @@ func main() { //-------------------------------------------------------------------------------------- // Main game loop - for !exitWindow && !rl.WindowShouldClose() { // Detect window close button or ESC key + for !(exitWindow || rl.WindowShouldClose() || exit_key) { // Detect window close button or ESC key // Update //---------------------------------------------------------------------------------- mousePosition = rl.GetMousePosition() diff --git a/examples/gui/scroll_panel/scroll_panel.go b/examples/gui/scroll_panel/main.go similarity index 92% rename from examples/gui/scroll_panel/scroll_panel.go rename to examples/gui/scroll_panel/main.go index dc6e207..2fbf478 100644 --- a/examples/gui/scroll_panel/scroll_panel.go +++ b/examples/gui/scroll_panel/main.go @@ -30,6 +30,8 @@ import ( * **********************************************************************************************/ +var exit_key = false + //------------------------------------------------------------------------------------ // Program main entry point //------------------------------------------------------------------------------------ @@ -56,7 +58,7 @@ func main() { //--------------------------------------------------------------------------------------- // Main game loop - for !rl.WindowShouldClose() { + for !(rl.WindowShouldClose() || exit_key) { // Detect window close button or ESC key // Update @@ -85,10 +87,10 @@ func main() { if showContentArea { rl.DrawRectangle( - int32(panelRec.X+panelScroll.X), - int32(panelRec.Y+panelScroll.Y), - int32(panelContentRec.Width), - int32(panelContentRec.Height), + int32(panelRec.X+panelScroll.X), + int32(panelRec.Y+panelScroll.Y), + int32(panelContentRec.Width), + int32(panelContentRec.Height), rl.Fade(rl.Red, 0.1), ) } @@ -140,7 +142,7 @@ func DrawStyleEditControls() { gui.Spinner(rl.Rectangle{670, 240, 90, 20}, "", &style, 0, 14, false) gui.SetStyle(gui.SCROLLBAR, gui.SLIDER_PADDING, style) - style = boolToint32( gui.CheckBox(rl.Rectangle{565, 280, 20, 20}, "ARROWS_VISIBLE", int32Tobool(gui.GetStyle(gui.SCROLLBAR, gui.ARROWS_VISIBLE)))) + style = boolToint32(gui.CheckBox(rl.Rectangle{565, 280, 20, 20}, "ARROWS_VISIBLE", int32Tobool(gui.GetStyle(gui.SCROLLBAR, gui.ARROWS_VISIBLE)))) gui.SetStyle(gui.SCROLLBAR, gui.ARROWS_VISIBLE, style) style = gui.GetStyle(gui.SCROLLBAR, gui.SLIDER_PADDING) @@ -159,7 +161,7 @@ func DrawStyleEditControls() { } else { text = "SCROLLBAR: RIGHT" } - style = boolToint32( gui.Toggle(rl.Rectangle{560, 110, 200, 35}, text, int32Tobool(gui.GetStyle(gui.LISTVIEW, gui.SCROLLBAR_SIDE)))) + style = boolToint32(gui.Toggle(rl.Rectangle{560, 110, 200, 35}, text, int32Tobool(gui.GetStyle(gui.LISTVIEW, gui.SCROLLBAR_SIDE)))) gui.SetStyle(gui.LISTVIEW, gui.SCROLLBAR_SIDE, style) //---------------------------------------------------------- diff --git a/raygui/go.mod b/raygui/go.mod index c2adde5..3822e0b 100644 --- a/raygui/go.mod +++ b/raygui/go.mod @@ -4,4 +4,4 @@ go 1.19 require github.com/gen2brain/raylib-go/raylib v0.0.0-20221117130019-ce3c8e83dd6d -replace github.com/gen2brain/raylib-go/raylib => ../../../raylib +replace github.com/gen2brain/raylib-go/raylib => ../raylib