merged from gramsrv upstream
This commit is contained in:
parent
79c64ee916
commit
21a0856587
651 changed files with 54774 additions and 4590 deletions
115
internal/app/userprojection/projection_sparse_test.go
Normal file
115
internal/app/userprojection/projection_sparse_test.go
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
package userprojection
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
privacyapp "telesrv/internal/app/privacy"
|
||||
"telesrv/internal/domain"
|
||||
"telesrv/internal/store"
|
||||
"telesrv/internal/store/memory"
|
||||
)
|
||||
|
||||
type recordingSparseContactStore struct {
|
||||
store.ContactStore
|
||||
sparseCalls int
|
||||
denseCalls int
|
||||
requested map[int64][]int64
|
||||
}
|
||||
|
||||
func (s *recordingSparseContactStore) ContactProjectionForViewers(ctx context.Context, viewers, owners []int64) (domain.ContactProjectionBatch, error) {
|
||||
s.denseCalls++
|
||||
return s.ContactStore.ContactProjectionForViewers(ctx, viewers, owners)
|
||||
}
|
||||
|
||||
func (s *recordingSparseContactStore) ContactProjectionForViewerUserIDs(ctx context.Context, requested map[int64][]int64) (domain.ContactProjectionBatch, error) {
|
||||
s.sparseCalls++
|
||||
s.requested = make(map[int64][]int64, len(requested))
|
||||
for viewerID, ids := range requested {
|
||||
s.requested[viewerID] = append([]int64(nil), ids...)
|
||||
}
|
||||
return s.ContactStore.(store.SparseContactProjectionStore).ContactProjectionForViewerUserIDs(ctx, requested)
|
||||
}
|
||||
|
||||
func TestForViewerUserIDsUsesActualPairsAndMatchesScalarProjection(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
const (
|
||||
viewerA = int64(1101)
|
||||
viewerB = int64(1102)
|
||||
ownerA = int64(2101)
|
||||
ownerB = int64(2102)
|
||||
)
|
||||
contacts := memory.NewContactStore()
|
||||
// Seed both requested and cross-viewer rows. A dense matrix would expose the
|
||||
// cross aliases/photos; the sparse request must never ask for those pairs.
|
||||
for _, input := range []struct {
|
||||
viewer int64
|
||||
owner int64
|
||||
name string
|
||||
photo int64
|
||||
}{
|
||||
{viewerA, ownerA, "A for viewer A", 9101},
|
||||
{viewerA, ownerB, "B cross leak", 9191},
|
||||
{viewerB, ownerB, "B for viewer B", 9102},
|
||||
{viewerB, ownerA, "A cross leak", 9192},
|
||||
// Reverse rows are the privacy ViewerIsContact facts.
|
||||
{ownerA, viewerA, "viewer A", 0},
|
||||
{ownerB, viewerB, "viewer B", 0},
|
||||
} {
|
||||
if _, err := contacts.Upsert(ctx, input.viewer, domain.ContactInput{ContactUserID: input.owner, FirstName: input.name}); err != nil {
|
||||
t.Fatalf("upsert %d->%d: %v", input.viewer, input.owner, err)
|
||||
}
|
||||
if input.photo != 0 {
|
||||
if _, _, err := contacts.SetPersonalPhoto(ctx, input.viewer, input.owner, input.photo, 100); err != nil {
|
||||
t.Fatalf("personal photo %d->%d: %v", input.viewer, input.owner, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
recording := &recordingSparseContactStore{ContactStore: contacts}
|
||||
privacy := privacyapp.NewService(memory.NewPrivacyStore(), recording)
|
||||
projector := New(WithContactStore(recording), WithPrivacyEvaluator(privacy))
|
||||
base := []domain.User{
|
||||
{ID: ownerA, AccessHash: 31, Phone: "15552101", FirstName: "Owner A"},
|
||||
{ID: ownerB, AccessHash: 32, Phone: "15552102", FirstName: "Owner B"},
|
||||
}
|
||||
wantA, err := projector.ForViewer(ctx, viewerA, base[:1])
|
||||
if err != nil {
|
||||
t.Fatalf("scalar viewer A: %v", err)
|
||||
}
|
||||
wantB, err := projector.ForViewer(ctx, viewerB, base[1:])
|
||||
if err != nil {
|
||||
t.Fatalf("scalar viewer B: %v", err)
|
||||
}
|
||||
recording.sparseCalls = 0
|
||||
recording.denseCalls = 0
|
||||
recording.requested = nil
|
||||
|
||||
got, err := projector.ForViewerUserIDs(ctx, map[int64][]int64{
|
||||
viewerA: {ownerA},
|
||||
viewerB: {ownerB},
|
||||
}, base)
|
||||
if err != nil {
|
||||
t.Fatalf("ForViewerUserIDs: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(got[viewerA], wantA) || !reflect.DeepEqual(got[viewerB], wantB) {
|
||||
t.Fatalf("sparse projection = %+v, want scalar A=%+v B=%+v", got, wantA, wantB)
|
||||
}
|
||||
if recording.sparseCalls != 1 || recording.denseCalls != 0 {
|
||||
t.Fatalf("contact projection calls = sparse %d dense %d, want 1/0", recording.sparseCalls, recording.denseCalls)
|
||||
}
|
||||
wantPairs := map[int64][]int64{
|
||||
viewerA: {ownerA},
|
||||
viewerB: {ownerB},
|
||||
ownerA: {viewerA},
|
||||
ownerB: {viewerB},
|
||||
}
|
||||
for viewerID, ids := range wantPairs {
|
||||
if !reflect.DeepEqual(recording.requested[viewerID], ids) {
|
||||
t.Fatalf("requested[%d] = %v, want %v (all=%+v)", viewerID, recording.requested[viewerID], ids, recording.requested)
|
||||
}
|
||||
}
|
||||
if len(recording.requested) != len(wantPairs) {
|
||||
t.Fatalf("requested pairs = %+v, contains unexpected cross-viewer edges", recording.requested)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue