package main import ( "bytes" "os" "path/filepath" "strings" "testing" "github.com/spf13/cobra" ) func newDryRunCmd() (*cobra.Command, *bytes.Buffer) { var buf bytes.Buffer cmd := &cobra.Command{} cmd.SetOut(&buf) return cmd, &buf } func TestRunConvert_DryRunWritesNothing(t *testing.T) { defer func(a, b, c, d string, e bool) { convertSourceType, convertSourcePath, convertTargetType, convertTargetPath, convertDryRun = a, b, c, d, e }(convertSourceType, convertSourcePath, convertTargetType, convertTargetPath, convertDryRun) dir := t.TempDir() in := filepath.Join(dir, "in.json") out := filepath.Join(dir, "out.json") writeTestJSON(t, in, []string{"users", "posts"}) convertSourceType, convertSourcePath = "json", in convertTargetType, convertTargetPath = "json", out convertDryRun = true cmd, buf := newDryRunCmd() if err := runConvert(cmd, nil); err != nil { t.Fatalf("dry run: %v", err) } if _, err := os.Stat(out); !os.IsNotExist(err) { t.Fatal("dry run must not create the output file") } for _, want := range []string{"dry run", "users", "posts", out} { if !strings.Contains(buf.String(), want) { t.Errorf("plan missing %q:\n%s", want, buf.String()) } } // Normal behavior is unchanged. convertDryRun = false if err := runConvert(cmd, nil); err != nil { t.Fatalf("real run: %v", err) } if _, err := os.Stat(out); err != nil { t.Fatalf("real run should write output: %v", err) } } func TestRunConvert_DryRunValidatesTarget(t *testing.T) { defer func(a, b, c, d string, e bool) { convertSourceType, convertSourcePath, convertTargetType, convertTargetPath, convertDryRun = a, b, c, d, e }(convertSourceType, convertSourcePath, convertTargetType, convertTargetPath, convertDryRun) dir := t.TempDir() in := filepath.Join(dir, "in.json") out := filepath.Join(dir, "models") writeTestJSON(t, in, []string{"users"}) convertSourceType, convertSourcePath = "json", in convertDryRun = true // gorm without --package must fail validation, as a real run would. convertTargetType, convertTargetPath = "gorm", out cmd, _ := newDryRunCmd() err := runConvert(cmd, nil) if err == nil || !strings.Contains(err.Error(), "package name is required") { t.Fatalf("expected package validation error, got %v", err) } convertTargetType = "nope" err = runConvert(cmd, nil) if err == nil || !strings.Contains(err.Error(), "unsupported target format") { t.Fatalf("expected unsupported format error, got %v", err) } if _, statErr := os.Stat(out); !os.IsNotExist(statErr) { t.Fatal("dry run must not create the output path") } } func TestRunSplit_DryRunWritesNothing(t *testing.T) { defer func(a, b, c, d, e string, f bool) { splitSourceType, splitSourcePath, splitTargetType, splitTargetPath, splitTables, splitDryRun = a, b, c, d, e, f }(splitSourceType, splitSourcePath, splitTargetType, splitTargetPath, splitTables, splitDryRun) dir := t.TempDir() in := filepath.Join(dir, "in.json") out := filepath.Join(dir, "subset.json") writeTestJSON(t, in, []string{"users", "posts", "comments"}) splitSourceType, splitSourcePath = "json", in splitTargetType, splitTargetPath = "json", out splitTables = "users,posts" splitDryRun = true cmd, buf := newDryRunCmd() if err := runSplit(cmd, nil); err != nil { t.Fatalf("dry run: %v", err) } if _, err := os.Stat(out); !os.IsNotExist(err) { t.Fatal("dry run must not create the output file") } got := buf.String() if !strings.Contains(got, "2 table(s)") || strings.Contains(got, "comments") { t.Errorf("plan should show only the 2 selected tables:\n%s", got) } // A selection that matches nothing fails validation in dry-run too. splitTables = "does_not_exist" if err := runSplit(cmd, nil); err == nil { t.Fatal("expected error for empty selection") } } func TestRunMerge_DryRunWritesNothing(t *testing.T) { saved := saveMergeState() defer restoreMergeState(saved) defer func(v bool) { mergeDryRun = v }(mergeDryRun) dir := t.TempDir() target := filepath.Join(dir, "target.json") source := filepath.Join(dir, "source.json") out := filepath.Join(dir, "merged.json") writeTestJSON(t, target, []string{"users"}) writeTestJSON(t, source, []string{"posts"}) mergeTargetType, mergeTargetPath, mergeTargetConn = "json", target, "" mergeSourceType, mergeSourcePath, mergeSourceConn = "json", source, "" mergeFromList = nil mergeOutputType, mergeOutputPath, mergeOutputConn = "json", out, "" mergeSkipTables, mergeReportPath = "", "" mergeDryRun = true cmd, buf := newDryRunCmd() if err := runMerge(cmd, nil); err != nil { t.Fatalf("dry run: %v", err) } if _, err := os.Stat(out); !os.IsNotExist(err) { t.Fatal("dry run must not create the output file") } for _, want := range []string{"dry run", "users", "posts", out} { if !strings.Contains(buf.String(), want) { t.Errorf("plan missing %q:\n%s", want, buf.String()) } } mergeOutputType = "nope" if err := runMerge(cmd, nil); err == nil || !strings.Contains(err.Error(), "unsupported format") { t.Fatalf("expected unsupported output format error, got %v", err) } }