71 lines
2.6 KiB
Go
71 lines
2.6 KiB
Go
package controlplane
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestContactSnapshotsReplaceOnlyAfterCompleteSync(t *testing.T) {
|
|
ctx := context.Background()
|
|
manager, err := OpenAccountStoreManager(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer manager.Close()
|
|
store, err := manager.RegisterAccount(ctx, AccountRegistration{
|
|
AccountID: "account-contacts", StableIdentity: "wechat-contacts", SourceNodeID: "node-contacts",
|
|
SourceGeneration: "generation-contacts", Verified: true, AuthorizationVersion: 1,
|
|
ReportingScopes: []ReportingScope{{ChatID: "*", DataType: "*", ConfigVersion: 1}},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer func() { _ = store.Close() }()
|
|
|
|
// Simulate an existing v1 shard so opening it exercises the contacts-table migration.
|
|
if _, err := store.db.ExecContext(ctx, `DROP TABLE contacts`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := store.db.ExecContext(ctx, `UPDATE schema_meta SET value = '1' WHERE key = 'schema_version'`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := store.Close(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
store, err = manager.OpenAccount(ctx, "account-contacts")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
now := time.Now().UTC()
|
|
private := ContactRecord{ChatID: "wxid-contact", ChatType: string(ChatPrivate), DisplayName: "Contact", Remark: "Local", ObservedAt: now}
|
|
group := ContactRecord{ChatID: "group@chatroom", ChatType: string(ChatGroup), DisplayName: "Group", ObservedAt: now}
|
|
apply := func(sequence int64, snapshotID, coverage string, contacts ...ContactRecord) error {
|
|
_, err := store.ApplyBatch(ctx, IngestBatch{
|
|
BatchID: "contacts-" + snapshotID, SourceGeneration: "generation-contacts", StreamKey: "contacts",
|
|
Sequence: sequence, CursorStart: "0", CursorEnd: "0", PayloadHash: "hash-" + snapshotID,
|
|
CoverageState: coverage, ContactsSnapshotID: snapshotID, Contacts: contacts,
|
|
})
|
|
return err
|
|
}
|
|
if err := apply(1, "snapshot-1", "complete", private, group); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if items, _, err := store.QueryContacts(ctx, "", true, 10, 0); err != nil || len(items) != 1 || items[0].ChatID != group.ChatID {
|
|
t.Fatalf("unexpected cached groups: %v %+v", err, items)
|
|
}
|
|
if err := apply(2, "snapshot-2", "partial", private); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if items, _, err := store.QueryContacts(ctx, "", true, 10, 0); err != nil || len(items) != 1 {
|
|
t.Fatalf("partial snapshot removed prior contacts: %v %+v", err, items)
|
|
}
|
|
if err := apply(3, "snapshot-3", "complete", private); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if items, _, err := store.QueryContacts(ctx, "", true, 10, 0); err != nil || len(items) != 0 {
|
|
t.Fatalf("complete snapshot did not remove stale contacts: %v %+v", err, items)
|
|
}
|
|
}
|