123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- package golang
- import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
- "testing"
- )
- func TestGolang(t *testing.T) {
- // Create a new Golang stack instance
- golangStack := &Golang{}
- // Test the Name method
- expectedName := "Golang"
- if golangStack.Name() != expectedName {
- t.Errorf("Expected name %s, got %s", expectedName, golangStack.Name())
- }
- }
- func TestAnalyze(t *testing.T) {
- golangStack := &Golang{}
- tests := []struct {
- name string
- setup func() string
- cleanup func(string)
- expected bool
- wantErr bool
- }{
- {
- name: "valid go project with go.mod",
- setup: func() string {
- tempDir, _ := os.MkdirTemp("", "test-go-project-")
- os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte("module test\ngo 1.21\n"), 0644)
- os.WriteFile(filepath.Join(tempDir, "main.go"), []byte("package main\nfunc main() {}\n"), 0644)
- return tempDir
- },
- cleanup: func(dir string) { os.RemoveAll(dir) },
- expected: true,
- wantErr: false,
- },
- {
- name: "valid go project with main.go only",
- setup: func() string {
- tempDir, _ := os.MkdirTemp("", "test-go-project-")
- os.WriteFile(filepath.Join(tempDir, "main.go"), []byte("package main\nfunc main() {}\n"), 0644)
- return tempDir
- },
- cleanup: func(dir string) { os.RemoveAll(dir) },
- expected: true,
- wantErr: false,
- },
- {
- name: "non-go project",
- setup: func() string {
- tempDir, _ := os.MkdirTemp("", "test-non-go-project-")
- os.WriteFile(filepath.Join(tempDir, "package.json"), []byte("{}"), 0644)
- return tempDir
- },
- cleanup: func(dir string) { os.RemoveAll(dir) },
- expected: false,
- wantErr: false,
- },
- {
- name: "empty directory",
- setup: func() string {
- tempDir, _ := os.MkdirTemp("", "test-empty-")
- return tempDir
- },
- cleanup: func(dir string) { os.RemoveAll(dir) },
- expected: false,
- wantErr: false,
- },
- {
- name: "non-existent directory",
- setup: func() string {
- return "/non/existent/path"
- },
- cleanup: func(dir string) {},
- expected: false,
- wantErr: true,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- codebasePath := tt.setup()
- defer tt.cleanup(codebasePath)
- isGo, err := golangStack.Analyze(codebasePath)
- if tt.wantErr && err == nil {
- t.Errorf("Expected error but got none")
- }
- if !tt.wantErr && err != nil {
- t.Errorf("Unexpected error: %v", err)
- }
- if isGo != tt.expected {
- t.Errorf("Expected %v, got %v", tt.expected, isGo)
- }
- })
- }
- }
- func TestFindMainPackage(t *testing.T) {
- golangStack := &Golang{}
- tests := []struct {
- name string
- setup func() string
- cleanup func(string)
- expected string
- }{
- {
- name: "main.go in root",
- setup: func() string {
- tempDir, _ := os.MkdirTemp("", "test-main-root-")
- os.WriteFile(filepath.Join(tempDir, "main.go"), []byte("package main\nfunc main() {}\n"), 0644)
- return tempDir
- },
- cleanup: func(dir string) { os.RemoveAll(dir) },
- expected: ".",
- },
- {
- name: "main.go in cmd/server",
- setup: func() string {
- tempDir, _ := os.MkdirTemp("", "test-cmd-server-")
- cmdDir := filepath.Join(tempDir, "cmd", "server")
- os.MkdirAll(cmdDir, 0755)
- os.WriteFile(filepath.Join(cmdDir, "main.go"), []byte("package main\nfunc main() {}\n"), 0644)
- return tempDir
- },
- cleanup: func(dir string) { os.RemoveAll(dir) },
- expected: "./cmd/server",
- },
- {
- name: "main function in cmd/web-server/app.go",
- setup: func() string {
- tempDir, _ := os.MkdirTemp("", "test-cmd-web-server-")
- cmdDir := filepath.Join(tempDir, "cmd", "web-server")
- os.MkdirAll(cmdDir, 0755)
- os.WriteFile(filepath.Join(cmdDir, "app.go"), []byte("package main\nfunc main() {}\n"), 0644)
- return tempDir
- },
- cleanup: func(dir string) { os.RemoveAll(dir) },
- expected: "./cmd/web-server",
- },
- {
- name: "no main package found",
- setup: func() string {
- tempDir, _ := os.MkdirTemp("", "test-no-main-")
- libDir := filepath.Join(tempDir, "lib")
- os.MkdirAll(libDir, 0755)
- os.WriteFile(filepath.Join(libDir, "helper.go"), []byte("package lib\nfunc Helper() {}\n"), 0644)
- return tempDir
- },
- cleanup: func(dir string) { os.RemoveAll(dir) },
- expected: ".",
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- codebasePath := tt.setup()
- defer tt.cleanup(codebasePath)
- result := golangStack.findMainPackage(codebasePath)
- if result != tt.expected {
- t.Errorf("Expected %q, got %q", tt.expected, result)
- }
- })
- }
- }
- func TestAnalyzeGoProject(t *testing.T) {
- golangStack := &Golang{}
- // Create a test project structure
- tempDir, err := os.MkdirTemp("", "test-analyze-project-")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempDir)
- // Create go.mod
- goMod := `module github.com/example/web-server
- go 1.21
- require (
- github.com/gin-gonic/gin v1.9.1
- )
- `
- os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte(goMod), 0644)
- // Create cmd/web-server/main.go
- cmdDir := filepath.Join(tempDir, "cmd", "web-server")
- os.MkdirAll(cmdDir, 0755)
- mainGo := `package main
- import (
- "net/http"
- "github.com/gin-gonic/gin"
- )
- func main() {
- r := gin.Default()
- r.GET("/", func(c *gin.Context) {
- c.JSON(http.StatusOK, gin.H{"message": "Hello World"})
- })
- r.Run(":8080")
- }
- `
- os.WriteFile(filepath.Join(cmdDir, "main.go"), []byte(mainGo), 0644)
- // Run analysis
- analysis, err := golangStack.analyzeGoProject(tempDir)
- if err != nil {
- t.Fatalf("Analysis failed: %v", err)
- }
- // Verify results
- if analysis.GoVersion != "1.21" {
- t.Errorf("Expected Go version 1.21, got %s", analysis.GoVersion)
- }
- if analysis.AppName != "web-server" {
- t.Errorf("Expected app name 'web-server', got %s", analysis.AppName)
- }
- if analysis.MainPackage != "./cmd/web-server" {
- t.Errorf("Expected main package './cmd/web-server', got %s", analysis.MainPackage)
- }
- if analysis.Port != 8080 {
- t.Errorf("Expected port 8080, got %d", analysis.Port)
- }
- if !analysis.RequiresCACerts {
- t.Error("Expected RequiresCACerts to be true (due to net/http import)")
- }
- if !contains(analysis.Modules, "gin") {
- t.Error("Expected gin module to be detected")
- }
- }
- func TestWebServerProjectStructure(t *testing.T) {
- // This test specifically replicates the structure from the failed build
- golangStack := &Golang{}
- tempDir, err := os.MkdirTemp("", "test-web-server-structure-")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempDir)
- // Create the directory structure that was failing
- os.MkdirAll(filepath.Join(tempDir, ".vscode"), 0755)
- os.MkdirAll(filepath.Join(tempDir, "cmd", "web-server"), 0755)
- os.MkdirAll(filepath.Join(tempDir, "configs"), 0755)
- os.MkdirAll(filepath.Join(tempDir, "pkg", "mhttp"), 0755)
- os.MkdirAll(filepath.Join(tempDir, "scripts"), 0755)
- os.MkdirAll(filepath.Join(tempDir, "tests"), 0755)
- os.MkdirAll(filepath.Join(tempDir, "web"), 0755)
- // Create files
- os.WriteFile(filepath.Join(tempDir, "LICENSE"), []byte("MIT License"), 0644)
- os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte("module golang-web-server\ngo 1.18\n"), 0644)
- // Create the main file in cmd/web-server (this should be detected)
- os.WriteFile(filepath.Join(tempDir, "cmd", "web-server", "golang-web-server.go"),
- []byte("package main\nfunc main() {}\n"), 0644)
- // Create other Go files that should NOT be chosen as main
- os.WriteFile(filepath.Join(tempDir, "pkg", "mhttp", "server.go"),
- []byte("package mhttp\nfunc StartServer() {}\n"), 0644)
- os.WriteFile(filepath.Join(tempDir, "pkg", "mhttp", "functions.go"),
- []byte("package mhttp\nfunc Handler() {}\n"), 0644)
- os.WriteFile(filepath.Join(tempDir, "configs", "server-config.go"),
- []byte("package configs\nvar Config = map[string]string{}\n"), 0644)
- // Test main package detection
- mainPackage := golangStack.findMainPackage(tempDir)
- if mainPackage != "./cmd/web-server" {
- t.Errorf("Expected main package './cmd/web-server', got '%s'", mainPackage)
- }
- // Test full analysis
- analysis, err := golangStack.analyzeGoProject(tempDir)
- if err != nil {
- t.Fatalf("Analysis failed: %v", err)
- }
- if analysis.MainPackage != "./cmd/web-server" {
- t.Errorf("Expected main package './cmd/web-server', got '%s'", analysis.MainPackage)
- }
- if analysis.AppName != "golang-web-server" {
- t.Errorf("Expected app name 'golang-web-server', got '%s'", analysis.AppName)
- }
- t.Logf("✅ Correctly detected main package: %s", analysis.MainPackage)
- t.Logf("✅ Correctly detected app name: %s", analysis.AppName)
- }
- func TestBuildCommandGeneration(t *testing.T) {
- tests := []struct {
- name string
- mainPackage string
- cgoEnabled bool
- expectedCommand string
- }{
- {
- name: "root package",
- mainPackage: ".",
- cgoEnabled: false,
- expectedCommand: "go build -ldflags='-w -s -extldflags \"-static\"' -a -installsuffix cgo -o testapp .",
- },
- {
- name: "cmd subdirectory",
- mainPackage: "cmd/server",
- cgoEnabled: false,
- expectedCommand: "go build -ldflags='-w -s -extldflags \"-static\"' -a -installsuffix cgo -o testapp ./cmd/server",
- },
- {
- name: "cmd subdirectory with CGO",
- mainPackage: "cmd/web-server",
- cgoEnabled: true,
- expectedCommand: "go build -ldflags='-w -s' -a -installsuffix cgo -o testapp ./cmd/web-server",
- },
- {
- name: "already has ./ prefix",
- mainPackage: "./cmd/api",
- cgoEnabled: false,
- expectedCommand: "go build -ldflags='-w -s -extldflags \"-static\"' -a -installsuffix cgo -o testapp ./cmd/api",
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- // Create test project
- tempDir, err := os.MkdirTemp("", "build-cmd-test-")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(tempDir)
- // Create minimal structure
- os.WriteFile(filepath.Join(tempDir, "go.mod"), []byte("module testapp\ngo 1.21\n"), 0644)
- // Mock the analysis result
- analysis := &GoProjectAnalysis{
- AppName: "testapp",
- MainPackage: tt.mainPackage,
- CGOEnabled: tt.cgoEnabled,
- }
- // Generate build command (simulate the logic from GenerateLLBAdvanced)
- appName := analysis.AppName
- if appName == "" {
- appName = "app"
- }
- var buildCmd string
- mainPackagePath := analysis.MainPackage
- if mainPackagePath != "." && !strings.HasPrefix(mainPackagePath, "./") {
- mainPackagePath = "./" + mainPackagePath
- }
- if analysis.CGOEnabled {
- buildCmd = fmt.Sprintf("go build -ldflags='-w -s' -a -installsuffix cgo -o %s %s",
- appName, mainPackagePath)
- } else {
- buildCmd = fmt.Sprintf("go build -ldflags='-w -s -extldflags \"-static\"' -a -installsuffix cgo -o %s %s",
- appName, mainPackagePath)
- }
- if buildCmd != tt.expectedCommand {
- t.Errorf("Expected command:\n%s\nGot:\n%s", tt.expectedCommand, buildCmd)
- }
- t.Logf("✅ Build command: %s", buildCmd)
- })
- }
- }
- // Helper function
- func contains(slice []string, item string) bool {
- for _, s := range slice {
- if s == item {
- return true
- }
- }
- return false
- }
|