Something went wrong. Try again.
An ATProto Powered Reputation Network
Something went wrong. Try again.
3.8 kB · 90 lines
Go
at master
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091package appview
import ( "context" "database/sql" "errors" "path/filepath" "testing" "time"
"provenance/internal/domain" "provenance/internal/storage" "provenance/internal/trust" "provenance/internal/trust/algorithms")
func TestSoftService(t *testing.T) { ctx := context.Background() path := filepath.Join(t.TempDir(), "soft.db") store, err := storage.OpenWithSoft(path, domain.SoftParticipants) if err != nil { t.Fatal(err) } defer store.Close() for _, did := range []string{alice, carol} { if err := store.Join(ctx, did); err != nil { t.Fatal(err) } } first := domain.Vouch{Author: alice, Subject: carol, Source: domain.FollowCollection, RecordKey: "follow", Score: domain.FollowScore} last := domain.Vouch{Author: carol, Subject: bob, Source: domain.BlockCollection, RecordKey: "block", Score: domain.SoftBlockScore} if err := store.Replace(ctx, alice, []domain.Vouch{first}, time.UnixMicro(100)); err != nil { t.Fatal(err) } if err := store.Replace(ctx, carol, []domain.Vouch{last}, time.UnixMicro(100)); err != nil { t.Fatal(err) } limits := trust.Limits{States: 100, Edges: 100, Penalty: domain.DefaultPenalty} disabledStore, err := storage.Open(path) if err != nil { t.Fatal(err) } defer disabledStore.Close() disabled := New(disabledStore, &repository{}, limits) got, err := disabled.Reputation(ctx, alice, bob, "", domain.Default) if err != nil || got.Status != trust.UnknownStatus { t.Fatalf("disabled score: %+v %v", got, err) } for _, algorithm := range []trust.Algorithm{algorithms.Optimistic{}, algorithms.ShortestPath{}} { s := NewWithOptions(store, &repository{}, limits, Options{Trust: algorithm, SoftMode: domain.SoftParticipants}) got, err := s.Reputation(ctx, alice, bob, "", domain.Default) if err != nil || got.Status != trust.CalculatedStatus || got.Score == nil || *got.Score != -.6 { t.Fatalf("soft path: %+v %v", got, err) } if len(got.PathScores) != 3 || got.PathScores[1].Source != domain.FollowCollection || got.PathScores[2].Source != domain.BlockCollection || *got.PathScores[1].Assertion != .5 || *got.PathScores[2].Assertion != -.5 { t.Fatalf("path provenance: %+v", got) } rep, err := s.RelativeReputation(ctx, alice, bob, "", domain.Default, .5) if err != nil || rep.AbsoluteScore != -.5 || rep.MeanScore != -.5 { t.Fatalf("soft reputation: %+v %v", rep, err) } rep, err = s.RelativeReputation(ctx, alice, bob, "work", domain.Tagged, .5) if err != nil || rep.Score != 0 { t.Fatalf("topic-only reputation: %+v %v", rep, err) } } allStore, err := storage.OpenWithSoft(path, domain.SoftAllAuthors) if err != nil { t.Fatal(err) } defer allStore.Close() const observer = "did:plc:observer" for _, v := range []domain.Vouch{{Author: alice, Subject: observer, Source: domain.FollowCollection, RecordKey: "observer", Score: .5}, {Author: observer, Subject: bob, Source: domain.FollowCollection, RecordKey: "follow", Score: .5}} { if err := allStore.Apply(ctx, "all-stream", domain.Change{Kind: domain.RecordChange, DID: v.Author, Source: v.Source, RecordKey: v.RecordKey, Vouch: &v, TimeUS: 200}); err != nil { t.Fatal(err) } } all := NewWithOptions(allStore, &repository{}, limits, Options{SoftMode: domain.SoftAllAuthors}) rep, err := all.RelativeReputation(ctx, alice, bob, "", domain.Default, .5) if err != nil || rep.Score != 0 || rep.MeanScore != 0 { t.Fatalf("all-author reputation: %+v %v", rep, err) } if _, err := allStore.Participant(ctx, observer); !errors.Is(err, sql.ErrNoRows) { t.Fatalf("observer enrollment: %v", err) } got, err = disabled.Reputation(ctx, alice, bob, "", domain.Default) if err != nil || got.Status != trust.UnknownStatus { t.Fatalf("disabled cache isolation: %+v %v", got, err) }}