Skip to content

Commit 26d5cd5

Browse files
committed
test: add P2P late-subscription relation validation test
Asserts that a merge succeeds when the relation target is absent on the receiving node — validateMergeRelationDocIDs skips rather than errors.
1 parent 5ed4c7a commit 26d5cd5

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2026 Democratized Data Foundation
2+
//
3+
// This file is part of the DefraDB test suite.
4+
//
5+
// The DefraDB test suite is licensed under either:
6+
//
7+
// (1) GNU Affero General Public License v3
8+
// (2) Business Source License 1.1
9+
//
10+
// See tests/LICENSE for details.
11+
12+
package peer
13+
14+
import (
15+
"testing"
16+
17+
"github.com/sourcenetwork/immutable"
18+
19+
"github.com/sourcenetwork/defradb/tests/action"
20+
testUtils "github.com/sourcenetwork/defradb/tests/integration"
21+
"github.com/sourcenetwork/defradb/tests/state"
22+
)
23+
24+
// TestP2PLateSub_BookWithRelation_RelationSkippedOnMerge_NoError asserts that when
25+
// a node subscribes to a document whose relation target it has never received,
26+
// the P2P merge succeeds. validateMergeRelationDocIDs treats a missing target as
27+
// a skip (the target may arrive later), so the merge is not rejected.
28+
//
29+
// Scenario:
30+
// 1. Node A creates Author and Book (linked). Node B does not subscribe yet.
31+
// 2. Peers connect. Node B subscribes only to the Book document.
32+
// 3. Node A updates the Book, triggering a sync event to Node B.
33+
// 4. Node B receives the merge but does not have Author locally → dangling link.
34+
// 5. The merge must succeed: Node B stores the Book with its _AuthorID intact
35+
// even though Author is absent.
36+
func TestP2PLateSub_BookWithRelation_RelationSkippedOnMerge_NoError(t *testing.T) {
37+
test := testUtils.TestCase{
38+
Actions: []any{
39+
testUtils.RandomNetworkingConfig(),
40+
testUtils.RandomNetworkingConfig(),
41+
&action.AddCollection{
42+
SDL: `
43+
type Author {
44+
Name: String
45+
Books: [Book]
46+
}
47+
type Book {
48+
Name: String
49+
Author: Author
50+
}
51+
`,
52+
},
53+
// Node 0: create Author (not synced because NodePeers don't auto-sync new docs).
54+
&action.AddDoc{
55+
NodeID: immutable.Some(0),
56+
CollectionID: 0,
57+
Doc: `{"Name": "Frank Herbert"}`,
58+
},
59+
// All nodes: create Book — both nodes will have this document.
60+
&action.AddDoc{
61+
CollectionID: 1,
62+
Doc: `{"Name": "Dune"}`,
63+
},
64+
testUtils.ConnectPeers{
65+
SourceNodeID: 0,
66+
TargetNodeID: 1,
67+
},
68+
// Node 1 subscribes to the Book document so it will receive future updates.
69+
// Author was never synced to Node 1.
70+
testUtils.AddDocumentSubscription{
71+
NodeID: 1,
72+
DocIDs: []state.ColDocIndex{
73+
state.NewColDocIndex(1, 0),
74+
},
75+
},
76+
// Node 0 links the Book to the Author. This triggers a sync event to Node 1.
77+
// DocMap uses NewDocIndex so the Author's real DocID is substituted at runtime.
78+
&action.UpdateDoc{
79+
NodeID: immutable.Some(0),
80+
CollectionID: 1,
81+
DocID: 0,
82+
DocMap: map[string]any{
83+
"_AuthorID": testUtils.NewDocIndex(0, 0),
84+
},
85+
},
86+
testUtils.WaitForSync{},
87+
// Node 1 should have received and stored the Book update.
88+
// Author is absent, but the merge must have succeeded (dangling link is
89+
// acceptable on the P2P merge path).
90+
&action.Request{
91+
NodeID: immutable.Some(1),
92+
Request: `query {
93+
Book {
94+
Name
95+
Author {
96+
Name
97+
}
98+
}
99+
}`,
100+
Results: map[string]any{
101+
"Book": []map[string]any{
102+
{
103+
"Name": "Dune",
104+
// Author not available on Node 1 — merge succeeded anyway.
105+
"Author": nil,
106+
},
107+
},
108+
},
109+
},
110+
},
111+
}
112+
113+
testUtils.ExecuteTestCase(t, test)
114+
}

0 commit comments

Comments
 (0)