1 package main 2 3 import ( 4 "archive/zip" 5 "flag" 6 "io" 7 "net/http" 8 "os" 9 "path/filepath" 10 "strings" 11 "testing" 12 13 "github.com/stretchr/testify/assert" 14 ) 15 16 func downloadAndExtractMetrics(t *testing.T, dest string) string { 17 t.Helper() 18 url := "https://github.com/cybertec-postgresql/pgwatch2/archive/refs/heads/master.zip" 19 resp, err := http.Get(url) 20 if err != nil { 21 t.Fatalf("failed to download zip: %v", err) 22 } 23 defer resp.Body.Close() 24 25 zipFile, err := os.CreateTemp("", "pgwatch2-*.zip") 26 if err != nil { 27 t.Fatalf("failed to create temp zip: %v", err) 28 } 29 defer os.Remove(zipFile.Name()) 30 31 _, err = io.Copy(zipFile, resp.Body) 32 if err != nil { 33 t.Fatalf("failed to save zip: %v", err) 34 } 35 zipFile.Close() 36 37 r, err := zip.OpenReader(zipFile.Name()) 38 if err != nil { 39 t.Fatalf("failed to open zip: %v", err) 40 } 41 defer r.Close() 42 43 var metricsRoot string 44 for _, f := range r.File { 45 if strings.HasSuffix(f.Name, "/metrics/") { 46 metricsRoot = f.Name 47 break 48 } 49 } 50 if metricsRoot == "" { 51 t.Fatal("metrics folder not found in zip") 52 } 53 54 var extracted string 55 for _, f := range r.File { 56 if strings.HasPrefix(f.Name, metricsRoot) { 57 rel := strings.TrimPrefix(f.Name, metricsRoot) 58 if rel == "" { 59 extracted = filepath.Join(dest, "metrics") 60 _ = os.MkdirAll(extracted, 0755) 61 continue 62 } 63 path := filepath.Join(dest, "metrics", rel) 64 if f.FileInfo().IsDir() { 65 _ = os.MkdirAll(path, 0755) 66 } else { 67 _ = os.MkdirAll(filepath.Dir(path), 0755) 68 out, err := os.Create(path) 69 if err != nil { 70 t.Fatalf("failed to create file: %v", err) 71 } 72 rc, err := f.Open() 73 if err != nil { 74 out.Close() 75 t.Fatalf("failed to open file in zip: %v", err) 76 } 77 _, _ = io.Copy(out, rc) 78 _ = out.Close() 79 _ = rc.Close() 80 } 81 } 82 } 83 return extracted 84 } 85 86 func TestMain_Integration(t *testing.T) { 87 tempDir := t.TempDir() 88 metricsDir := downloadAndExtractMetrics(t, tempDir) 89 dstFile := filepath.Join(tempDir, "out.yaml") 90 91 t.Run("success", func(t *testing.T) { 92 flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) 93 os.Args = []string{"convert_metrics", "-src", metricsDir, "-dst", dstFile} 94 main() 95 data, err := os.ReadFile(dstFile) 96 if err != nil { 97 t.Fatalf("output file not created: %v", err) 98 } 99 if !strings.Contains(string(data), "metrics:") { 100 t.Errorf("output missing metrics key") 101 } 102 if !strings.Contains(string(data), "presets:") { 103 t.Errorf("output missing presets key") 104 } 105 }) 106 107 t.Run("missing_cmd_opts", func(t *testing.T) { 108 flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) 109 os.Args = []string{"convert_metrics"} 110 assert.NotPanics(t, func() { main() }) 111 }) 112 113 } 114 115 func TestMain_getArgs(t *testing.T) { 116 t.Run("missing_both", func(t *testing.T) { 117 flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) 118 os.Args = []string{"convert_metrics"} 119 assert.Error(t, getArgs(flag.String("src", "", ""), flag.String("dst", "", ""))) 120 }) 121 t.Run("missing_dst", func(t *testing.T) { 122 flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) 123 os.Args = []string{"convert_metrics", "-src", "foo"} 124 assert.Error(t, getArgs(flag.String("src", "", ""), flag.String("dst", "", ""))) 125 }) 126 t.Run("missing_src", func(t *testing.T) { 127 flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) 128 os.Args = []string{"convert_metrics", "-dst", "foo"} 129 assert.Error(t, getArgs(flag.String("src", "", ""), flag.String("dst", "", ""))) 130 }) 131 } 132