This repository has no description
1package models
2
3import (
4 "encoding/json"
5 "testing"
6
7 "github.com/ipfs/go-cid"
8
9 lexutil "github.com/bluesky-social/indigo/lex/util"
10)
11
12// two distinct, valid CIDv1 strings for use as blob refs
13const (
14 cidA = "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi"
15 cidB = "bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku"
16)
17
18func blobJSON(t *testing.T, cidStr, mime string) string {
19 t.Helper()
20 c, err := cid.Decode(cidStr)
21 if err != nil {
22 t.Fatalf("decode cid: %v", err)
23 }
24 b := lexutil.LexBlob{Ref: lexutil.LexLink(c), MimeType: mime, Size: 1234}
25 raw, err := json.Marshal(b)
26 if err != nil {
27 t.Fatalf("marshal blob: %v", err)
28 }
29 return string(raw)
30}
31
32func cids(blobs []*lexutil.LexBlob) []string {
33 out := make([]string, len(blobs))
34 for i, b := range blobs {
35 out[i] = b.Ref.String()
36 }
37 return out
38}
39
40func TestParseBlobs(t *testing.T) {
41 ja := blobJSON(t, cidA, "image/png")
42 jb := blobJSON(t, cidB, "image/jpeg")
43 body := "look:  and nothing else"
44
45 t.Run("keeps referenced, drops unreferenced", func(t *testing.T) {
46 got := ParseBlobs([]string{ja, jb}, body)
47 if len(got) != 1 || got[0].Ref.String() != cidA {
48 t.Fatalf("got %v, want [%s]", cids(got), cidA)
49 }
50 })
51
52 t.Run("dedups repeated cid", func(t *testing.T) {
53 got := ParseBlobs([]string{ja, ja}, body)
54 if len(got) != 1 {
55 t.Fatalf("got %d blobs, want 1", len(got))
56 }
57 })
58
59 t.Run("ignores malformed json", func(t *testing.T) {
60 got := ParseBlobs([]string{"not json", ja}, body)
61 if len(got) != 1 {
62 t.Fatalf("got %d blobs, want 1", len(got))
63 }
64 })
65
66 t.Run("empty input", func(t *testing.T) {
67 if got := ParseBlobs(nil, body); got != nil {
68 t.Fatalf("got %v, want nil", cids(got))
69 }
70 })
71}
72
73func TestMergeBlobs(t *testing.T) {
74 ja := blobJSON(t, cidA, "image/png")
75 jb := blobJSON(t, cidB, "image/jpeg")
76
77 ca, _ := cid.Decode(cidA)
78 existing := []*lexutil.LexBlob{{Ref: lexutil.LexLink(ca), MimeType: "image/png", Size: 1234}}
79
80 // body references both A (existing) and B (new upload)
81 body := " "
82
83 t.Run("union of existing and new, both referenced", func(t *testing.T) {
84 got := ParseBlobsSet(MergeBlobs(existing, []string{jb}, body))
85 if !got[cidA] || !got[cidB] || len(got) != 2 {
86 t.Fatalf("got %v, want {%s,%s}", got, cidA, cidB)
87 }
88 })
89
90 t.Run("drops existing no longer in body", func(t *testing.T) {
91 bodyOnlyB := ""
92 got := MergeBlobs(existing, []string{jb}, bodyOnlyB)
93 if len(got) != 1 || got[0].Ref.String() != cidB {
94 t.Fatalf("got %v, want [%s]", cids(got), cidB)
95 }
96 })
97
98 t.Run("no double-count when new equals existing", func(t *testing.T) {
99 got := MergeBlobs(existing, []string{ja}, body)
100 if len(got) != 1 || got[0].Ref.String() != cidA {
101 t.Fatalf("got %v, want [%s]", cids(got), cidA)
102 }
103 })
104}
105
106func ParseBlobsSet(blobs []*lexutil.LexBlob) map[string]bool {
107 m := make(map[string]bool, len(blobs))
108 for _, b := range blobs {
109 m[b.Ref.String()] = true
110 }
111 return m
112}