| 1 | package upgradefixture |
| 2 | |
| 3 | import ( |
| 4 | "encoding/json" |
| 5 | "os" |
| 6 | "path/filepath" |
| 7 | "strings" |
| 8 | "testing" |
| 9 | ) |
| 10 | |
| 11 | func TestEncodeLegacyHistoryEscapesJSONContent(t *testing.T) { |
| 12 | want := []legacyMessage{ |
| 13 | {Role: "user", Content: "quote \" slash \\ newline\n中文 %20 #"}, |
| 14 | {Role: "assistant", Content: "second line"}, |
| 15 | } |
| 16 | body, err := encodeLegacyHistory(want...) |
| 17 | if err != nil { |
| 18 | t.Fatal(err) |
| 19 | } |
| 20 | lines := strings.Split(strings.TrimSuffix(string(body), "\n"), "\n") |
| 21 | if len(lines) != len(want) { |
| 22 | t.Fatalf("encoded lines = %d, want %d: %q", len(lines), len(want), body) |
| 23 | } |
| 24 | for i, line := range lines { |
| 25 | var got legacyMessage |
| 26 | if err := json.Unmarshal([]byte(line), &got); err != nil { |
| 27 | t.Fatalf("decode line %d: %v", i, err) |
| 28 | } |
| 29 | if got != want[i] { |
| 30 | t.Fatalf("line %d = %+v, want %+v", i, got, want[i]) |
| 31 | } |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | func TestRunRestoresEnvironmentOnSuccessAndFailure(t *testing.T) { |
| 36 | for _, key := range []string{"REASONIX_HOME", "REASONIX_STATE_HOME", "REASONIX_CACHE_HOME"} { |
| 37 | t.Setenv(key, "untouched-"+key) |
| 38 | } |
| 39 | home := filepath.Join(t.TempDir(), "isolated") |
| 40 | report := filepath.Join(t.TempDir(), "fixture.json") |
| 41 | for _, mode := range []string{"create", "verify", "invalid"} { |
| 42 | err := Run(mode, home, report, "first") |
| 43 | if mode == "create" && err != nil { |
| 44 | t.Fatal(err) |
| 45 | } |
| 46 | if mode != "create" && err == nil { |
| 47 | t.Fatalf("%s must fail before migration", mode) |
| 48 | } |
| 49 | for _, key := range []string{"REASONIX_HOME", "REASONIX_STATE_HOME", "REASONIX_CACHE_HOME"} { |
| 50 | if got := os.Getenv(key); got != "untouched-"+key { |
| 51 | t.Fatalf("%s leaked %s=%q", mode, key, got) |
| 52 | } |
| 53 | } |
| 54 | } |
| 55 | } |
| 56 |