subscription_run_test.go
| 1 | package service |
| 2 | |
| 3 | import ( |
| 4 | "encoding/json" |
| 5 | "os" |
| 6 | "path/filepath" |
| 7 | "testing" |
| 8 | ) |
| 9 | |
| 10 | func TestApplyMetadataPreservesEngagementAndPermissions(t *testing.T) { |
| 11 | e := newExecEnv(t) |
| 12 | existing := writeItem(t, e.cfg.LibraryDir, "existing", `name = "Old" |
| 13 | video_id = "old" |
| 14 | `, map[string]string{ |
| 15 | "video.mp4": "dummy", |
| 16 | "info.json": `{"id":"old","title":"Old","comments":[{"id":"c1","text":"archived"}],"heatmap":[{"start_time":0,"end_time":1,"value":1}],"filesize":123}`, |
| 17 | }) |
| 18 | source := filepath.Join(e.scratch, "refreshed.info.json") |
| 19 | if err := os.WriteFile(source, []byte(`{"id":"new","title":"New","description":"updated","comments":[]}`), 0644); err != nil { |
| 20 | t.Fatal(err) |
| 21 | } |
| 22 | |
| 23 | if err := e.svc.applyMetadata(existing, infoJSON{ID: "new", Title: "New", Description: "updated"}, source); err != nil { |
| 24 | t.Fatalf("applyMetadata: %v", err) |
| 25 | } |
| 26 | |
| 27 | data, err := os.ReadFile(filepath.Join(existing, "info.json")) |
| 28 | if err != nil { |
| 29 | t.Fatal(err) |
| 30 | } |
| 31 | var got map[string]json.RawMessage |
| 32 | if err := json.Unmarshal(data, &got); err != nil { |
| 33 | t.Fatalf("parse installed info JSON: %v", err) |
| 34 | } |
| 35 | if _, ok := got["comments"]; !ok { |
| 36 | t.Fatal("refreshed sidecar lost archived comments") |
| 37 | } |
| 38 | if _, ok := got["heatmap"]; !ok { |
| 39 | t.Fatal("refreshed sidecar lost archived heatmap") |
| 40 | } |
| 41 | if string(got["title"]) != `"New"` { |
| 42 | t.Errorf("title = %s, want New", got["title"]) |
| 43 | } |
| 44 | if mode := fileMode(t, filepath.Join(existing, "info.json")); mode != 0644 { |
| 45 | t.Errorf("info.json mode = %o, want 0644", mode) |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | func TestApplyMetadataRollsBackMarkerWhenSidecarInstallFails(t *testing.T) { |
| 50 | e := newExecEnv(t) |
| 51 | existing := writeItem(t, e.cfg.LibraryDir, "rollback", `name = "Old" |
| 52 | video_id = "old" |
| 53 | `, map[string]string{"video.mp4": "dummy"}) |
| 54 | markerPath := filepath.Join(existing, itemMarkerName) |
| 55 | before, err := os.ReadFile(markerPath) |
| 56 | if err != nil { |
| 57 | t.Fatal(err) |
| 58 | } |
| 59 | // A directory at the destination makes the final rename fail after the |
| 60 | // marker has been written, exercising the rollback path. |
| 61 | infoPath := filepath.Join(existing, "info.json") |
| 62 | if err := os.Mkdir(infoPath, 0755); err != nil { |
| 63 | t.Fatal(err) |
| 64 | } |
| 65 | source := filepath.Join(e.scratch, "rollback.info.json") |
| 66 | if err := os.WriteFile(source, []byte(`{"id":"new","title":"New"}`), 0644); err != nil { |
| 67 | t.Fatal(err) |
| 68 | } |
| 69 | |
| 70 | if err := e.svc.applyMetadata(existing, infoJSON{ID: "new", Title: "New"}, source); err == nil { |
| 71 | t.Fatal("expected sidecar installation to fail") |
| 72 | } |
| 73 | after, err := os.ReadFile(markerPath) |
| 74 | if err != nil { |
| 75 | t.Fatal(err) |
| 76 | } |
| 77 | if string(after) != string(before) { |
| 78 | t.Errorf("marker changed after failed sidecar install:\nbefore: %s\nafter: %s", before, after) |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | func fileMode(t *testing.T, path string) os.FileMode { |
| 83 | t.Helper() |
| 84 | info, err := os.Stat(path) |
| 85 | if err != nil { |
| 86 | t.Fatal(err) |
| 87 | } |
| 88 | return info.Mode().Perm() |
| 89 | } |
| 90 |