porting all github actions from bluesky-social/indigo to tangled CI
at main 5.1 kB view raw
1package repomgr 2 3import ( 4 "bytes" 5 "context" 6 "fmt" 7 "os" 8 "path/filepath" 9 "strings" 10 "testing" 11 12 atproto "github.com/bluesky-social/indigo/api/atproto" 13 bsky "github.com/bluesky-social/indigo/api/bsky" 14 "github.com/bluesky-social/indigo/carstore" 15 "github.com/bluesky-social/indigo/models" 16 "github.com/bluesky-social/indigo/repo" 17 "github.com/bluesky-social/indigo/util" 18 "github.com/ipfs/go-cid" 19 "gorm.io/driver/sqlite" 20 "gorm.io/gorm" 21) 22 23func skipIfNoFile(t *testing.T, f string) { 24 t.Helper() 25 _, err := os.Stat(f) 26 if err != nil { 27 if os.IsNotExist(err) { 28 t.Skipf("test vector %s not present, skipping for now", f) 29 } 30 31 t.Fatal(err) 32 } 33} 34 35func TestLoadNewRepo(t *testing.T) { 36 skipIfNoFile(t, "testrepo.car") 37 38 dir, err := os.MkdirTemp("", "integtest") 39 if err != nil { 40 t.Fatal(err) 41 } 42 43 cardb, err := gorm.Open(sqlite.Open(filepath.Join(dir, "car.sqlite"))) 44 if err != nil { 45 t.Fatal(err) 46 } 47 48 cspath := filepath.Join(dir, "carstore") 49 if err := os.Mkdir(cspath, 0775); err != nil { 50 t.Fatal(err) 51 } 52 53 cs, err := carstore.NewCarStore(cardb, []string{cspath}) 54 if err != nil { 55 t.Fatal(err) 56 } 57 58 repoman := NewRepoManager(cs, &util.FakeKeyManager{}) 59 60 fi, err := os.Open("../testing/testdata/divy.repo") 61 if err != nil { 62 t.Fatal(err) 63 } 64 defer fi.Close() 65 66 ctx := context.TODO() 67 if err := repoman.ImportNewRepo(ctx, 2, "", fi, nil); err != nil { 68 t.Fatal(err) 69 } 70} 71 72func testCarstore(t *testing.T, dir string, archive bool) carstore.CarStore { 73 cardb, err := gorm.Open(sqlite.Open(filepath.Join(dir, "car.sqlite"))) 74 if err != nil { 75 t.Fatal(err) 76 } 77 78 cspath := filepath.Join(dir, "carstore") 79 if err := os.Mkdir(cspath, 0775); err != nil { 80 t.Fatal(err) 81 } 82 83 if archive { 84 cs, err := carstore.NewCarStore(cardb, []string{cspath}) 85 if err != nil { 86 t.Fatal(err) 87 } 88 return cs 89 } else { 90 cs, err := carstore.NewNonArchivalCarstore(cardb) 91 if err != nil { 92 t.Fatal(err) 93 } 94 95 return cs 96 } 97} 98 99func TestIngestWithGap(t *testing.T) { 100 dir, err := os.MkdirTemp("", "integtest") 101 if err != nil { 102 t.Fatal(err) 103 } 104 105 maindb, err := gorm.Open(sqlite.Open(filepath.Join(dir, "test.sqlite"))) 106 if err != nil { 107 t.Fatal(err) 108 } 109 maindb.AutoMigrate(models.ActorInfo{}) 110 111 did := "did:plc:beepboop" 112 maindb.Create(&models.ActorInfo{ 113 Did: did, 114 Uid: 1, 115 }) 116 117 cs := testCarstore(t, dir, true) 118 119 repoman := NewRepoManager(cs, &util.FakeKeyManager{}) 120 121 dir2, err := os.MkdirTemp("", "integtest") 122 if err != nil { 123 t.Fatal(err) 124 } 125 cs2 := testCarstore(t, dir2, true) 126 127 var since *string 128 ctx := context.TODO() 129 for i := 0; i < 5; i++ { 130 slice, _, nrev, tid := doPost(t, cs2, did, since, i) 131 132 ops := []*atproto.SyncSubscribeRepos_RepoOp{ 133 { 134 Action: "create", 135 Path: "app.bsky.feed.post/" + tid, 136 }, 137 } 138 139 if err := repoman.HandleExternalUserEvent(ctx, 1, 1, did, since, nrev, slice, ops); err != nil { 140 t.Fatal(err) 141 } 142 143 since = &nrev 144 } 145 146 // now do a few outside of the standard event stream flow 147 for i := 0; i < 5; i++ { 148 _, _, nrev, _ := doPost(t, cs2, did, since, i) 149 since = &nrev 150 } 151 152 buf := new(bytes.Buffer) 153 if err := cs2.ReadUserCar(ctx, 1, "", true, buf); err != nil { 154 t.Fatal(err) 155 } 156 157 if err := repoman.ImportNewRepo(ctx, 1, did, buf, nil); err != nil { 158 t.Fatal(err) 159 } 160} 161 162func doPost(t *testing.T, cs carstore.CarStore, did string, prev *string, postid int) ([]byte, cid.Cid, string, string) { 163 ctx := context.TODO() 164 ds, err := cs.NewDeltaSession(ctx, 1, prev) 165 if err != nil { 166 t.Fatal(err) 167 } 168 169 r := repo.NewRepo(ctx, did, ds) 170 171 _, tid, err := r.CreateRecord(ctx, "app.bsky.feed.post", &bsky.FeedPost{ 172 Text: fmt.Sprintf("hello friend %d", postid), 173 }) 174 if err != nil { 175 t.Fatal(err) 176 } 177 178 root, nrev, err := r.Commit(ctx, func(context.Context, string, []byte) ([]byte, error) { return nil, nil }) 179 if err != nil { 180 t.Fatal(err) 181 } 182 183 slice, err := ds.CloseWithRoot(ctx, root, nrev) 184 if err != nil { 185 t.Fatal(err) 186 } 187 188 return slice, root, nrev, tid 189} 190 191func TestDuplicateRecord(t *testing.T) { 192 dir, err := os.MkdirTemp("", "integtest") 193 if err != nil { 194 t.Fatal(err) 195 } 196 197 maindb, err := gorm.Open(sqlite.Open(filepath.Join(dir, "test.sqlite"))) 198 if err != nil { 199 t.Fatal(err) 200 } 201 maindb.AutoMigrate(models.ActorInfo{}) 202 203 did := "did:plc:beepboop" 204 maindb.Create(&models.ActorInfo{ 205 Did: did, 206 Uid: 1, 207 }) 208 209 cs := testCarstore(t, dir, true) 210 211 repoman := NewRepoManager(cs, &util.FakeKeyManager{}) 212 213 ctx := context.TODO() 214 if err := repoman.InitNewActor(ctx, 1, "hello.world", "did:plc:foobar", "", "", ""); err != nil { 215 t.Fatal(err) 216 } 217 218 p1, _, err := repoman.CreateRecord(ctx, 1, "app.bsky.feed.post", &bsky.FeedPost{ 219 Text: "hello friend", 220 }) 221 if err != nil { 222 t.Fatal(err) 223 } 224 225 p2, _, err := repoman.CreateRecord(ctx, 1, "app.bsky.feed.post", &bsky.FeedPost{ 226 Text: "hello friend", 227 }) 228 if err != nil { 229 t.Fatal(err) 230 } 231 232 rkey2 := strings.Split(p2, "/")[1] 233 if err := repoman.DeleteRecord(ctx, 1, "app.bsky.feed.post", rkey2); err != nil { 234 t.Fatal(err) 235 } 236 237 rkey1 := strings.Split(p1, "/")[1] 238 c, rec, err := repoman.GetRecord(ctx, 1, "app.bsky.feed.post", rkey1, cid.Undef) 239 if err != nil { 240 t.Fatal(err) 241 } 242 243 _ = c 244 _ = rec 245}