Skip to content

Commit a1e8307

Browse files
committed
cre-1601: improved test for plugin outcome
1 parent 0bd0aaf commit a1e8307

File tree

1 file changed

+96
-94
lines changed

1 file changed

+96
-94
lines changed

pkg/workflows/ring/plugin_test.go

Lines changed: 96 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -22,111 +22,113 @@ var twoHealthyShards = []map[uint32]bool{
2222
{0: true, 1: true},
2323
}
2424

25-
func TestPlugin_OutcomeWithMultiNodeObservations(t *testing.T) {
26-
lggr := logger.Test(t)
27-
store := NewStore()
28-
store.SetAllShardHealth(map[uint32]bool{0: true, 1: true, 2: true})
25+
func TestPlugin_Outcome(t *testing.T) {
26+
t.Run("WithMultiNodeObservations", func(t *testing.T) {
27+
lggr := logger.Test(t)
28+
store := NewStore()
29+
store.SetAllShardHealth(map[uint32]bool{0: true, 1: true, 2: true})
30+
31+
config := ocr3types.ReportingPluginConfig{
32+
N: 4, F: 1,
33+
OffchainConfig: []byte{},
34+
MaxDurationObservation: 0,
35+
MaxDurationShouldAcceptAttestedReport: 0,
36+
MaxDurationShouldTransmitAcceptedReport: 0,
37+
}
2938

30-
config := ocr3types.ReportingPluginConfig{
31-
N: 4, F: 1,
32-
OffchainConfig: []byte{},
33-
MaxDurationObservation: 0,
34-
MaxDurationShouldAcceptAttestedReport: 0,
35-
MaxDurationShouldTransmitAcceptedReport: 0,
36-
}
39+
plugin, err := NewPlugin(store, config, lggr, nil)
40+
require.NoError(t, err)
3741

38-
plugin, err := NewPlugin(store, config, lggr, nil)
39-
require.NoError(t, err)
42+
ctx := t.Context()
43+
intialSeqNr := uint64(42)
44+
outcomeCtx := ocr3types.OutcomeContext{SeqNr: intialSeqNr}
45+
46+
// Observations from 4 NOPs reporting health and workflows
47+
observations := []struct {
48+
name string
49+
shardHealth map[uint32]bool
50+
workflows []string
51+
}{
52+
{
53+
name: "NOP 0",
54+
shardHealth: map[uint32]bool{0: true, 1: true, 2: true},
55+
workflows: []string{"wf-A", "wf-B", "wf-C"},
56+
},
57+
{
58+
name: "NOP 1",
59+
shardHealth: map[uint32]bool{0: true, 1: true, 2: true},
60+
workflows: []string{"wf-B", "wf-C", "wf-D"},
61+
},
62+
{
63+
name: "NOP 2",
64+
shardHealth: map[uint32]bool{0: true, 1: true, 2: false}, // shard 2 unhealthy
65+
workflows: []string{"wf-A", "wf-C"},
66+
},
67+
{
68+
name: "NOP 3",
69+
shardHealth: map[uint32]bool{0: true, 1: true, 2: true},
70+
workflows: []string{"wf-A", "wf-B", "wf-D"},
71+
},
72+
}
4073

41-
ctx := t.Context()
42-
intialSeqNr := uint64(42)
43-
outcomeCtx := ocr3types.OutcomeContext{SeqNr: intialSeqNr}
44-
45-
// Observations from 4 NOPs reporting health and workflows
46-
observations := []struct {
47-
name string
48-
shardHealth map[uint32]bool
49-
workflows []string
50-
}{
51-
{
52-
name: "NOP 0",
53-
shardHealth: map[uint32]bool{0: true, 1: true, 2: true},
54-
workflows: []string{"wf-A", "wf-B", "wf-C"},
55-
},
56-
{
57-
name: "NOP 1",
58-
shardHealth: map[uint32]bool{0: true, 1: true, 2: true},
59-
workflows: []string{"wf-B", "wf-C", "wf-D"},
60-
},
61-
{
62-
name: "NOP 2",
63-
shardHealth: map[uint32]bool{0: true, 1: true, 2: false}, // shard 2 unhealthy
64-
workflows: []string{"wf-A", "wf-C"},
65-
},
66-
{
67-
name: "NOP 3",
68-
shardHealth: map[uint32]bool{0: true, 1: true, 2: true},
69-
workflows: []string{"wf-A", "wf-B", "wf-D"},
70-
},
71-
}
74+
// Build attributed observations
75+
aos := make([]types.AttributedObservation, 0)
76+
for _, obs := range observations {
77+
pbObs := &pb.Observation{
78+
ShardHealthStatus: obs.shardHealth,
79+
WorkflowIds: obs.workflows,
80+
Now: timestamppb.Now(),
81+
}
82+
rawObs, err := proto.Marshal(pbObs)
83+
require.NoError(t, err)
7284

73-
// Build attributed observations
74-
aos := make([]types.AttributedObservation, 0)
75-
for _, obs := range observations {
76-
pbObs := &pb.Observation{
77-
ShardHealthStatus: obs.shardHealth,
78-
WorkflowIds: obs.workflows,
79-
Now: timestamppb.Now(),
85+
aos = append(aos, types.AttributedObservation{
86+
Observation: rawObs,
87+
Observer: commontypes.OracleID(len(aos)),
88+
})
8089
}
81-
rawObs, err := proto.Marshal(pbObs)
82-
require.NoError(t, err)
8390

84-
aos = append(aos, types.AttributedObservation{
85-
Observation: rawObs,
86-
Observer: commontypes.OracleID(len(aos)),
87-
})
88-
}
89-
90-
// Execute Outcome phase
91-
outcome, err := plugin.Outcome(ctx, outcomeCtx, nil, aos)
92-
require.NoError(t, err)
93-
require.NotNil(t, outcome)
91+
// Execute Outcome phase
92+
outcome, err := plugin.Outcome(ctx, outcomeCtx, nil, aos)
93+
require.NoError(t, err)
94+
require.NotNil(t, outcome)
9495

95-
// Verify outcome
96-
outcomeProto := &pb.Outcome{}
97-
err = proto.Unmarshal(outcome, outcomeProto)
98-
require.NoError(t, err)
96+
// Verify outcome
97+
outcomeProto := &pb.Outcome{}
98+
err = proto.Unmarshal(outcome, outcomeProto)
99+
require.NoError(t, err)
99100

100-
// Check consensus results
101-
require.NotNil(t, outcomeProto.State)
102-
require.Equal(t, intialSeqNr+1, outcomeProto.State.Id, "ID should match SeqNr")
103-
t.Logf("Outcome - ID: %d, HealthyShards: %v", outcomeProto.State.Id, outcomeProto.State.GetRoutableShards())
104-
t.Logf("Workflows assigned: %d", len(outcomeProto.Routes))
105-
106-
// Verify all workflows are assigned
107-
expectedWorkflows := map[string]bool{"wf-A": true, "wf-B": true, "wf-C": true, "wf-D": true}
108-
require.Equal(t, len(expectedWorkflows), len(outcomeProto.Routes))
109-
for wf := range expectedWorkflows {
110-
route, exists := outcomeProto.Routes[wf]
111-
require.True(t, exists, "workflow %s should be assigned", wf)
112-
require.True(t, route.Shard <= 2, "shard should be healthy (0-2)")
113-
t.Logf(" %s → shard %d", wf, route.Shard)
114-
}
101+
// Check consensus results
102+
require.NotNil(t, outcomeProto.State)
103+
require.Equal(t, intialSeqNr+1, outcomeProto.State.Id, "ID should match SeqNr")
104+
t.Logf("Outcome - ID: %d, HealthyShards: %v", outcomeProto.State.Id, outcomeProto.State.GetRoutableShards())
105+
t.Logf("Workflows assigned: %d", len(outcomeProto.Routes))
106+
107+
// Verify all workflows are assigned
108+
expectedWorkflows := map[string]bool{"wf-A": true, "wf-B": true, "wf-C": true, "wf-D": true}
109+
require.Equal(t, len(expectedWorkflows), len(outcomeProto.Routes))
110+
for wf := range expectedWorkflows {
111+
route, exists := outcomeProto.Routes[wf]
112+
require.True(t, exists, "workflow %s should be assigned", wf)
113+
require.True(t, route.Shard <= 2, "shard should be healthy (0-2)")
114+
t.Logf(" %s → shard %d", wf, route.Shard)
115+
}
115116

116-
// Verify determinism: run again, should get same assignments
117-
outcome2, err := plugin.Outcome(ctx, outcomeCtx, nil, aos)
118-
require.NoError(t, err)
117+
// Verify determinism: run again, should get same assignments
118+
outcome2, err := plugin.Outcome(ctx, outcomeCtx, nil, aos)
119+
require.NoError(t, err)
119120

120-
outcomeProto2 := &pb.Outcome{}
121-
err = proto.Unmarshal(outcome2, outcomeProto2)
122-
require.NoError(t, err)
121+
outcomeProto2 := &pb.Outcome{}
122+
err = proto.Unmarshal(outcome2, outcomeProto2)
123+
require.NoError(t, err)
123124

124-
// Same workflows → same shards
125-
for wf, route1 := range outcomeProto.Routes {
126-
route2, exists := outcomeProto2.Routes[wf]
127-
require.True(t, exists)
128-
require.Equal(t, route1.Shard, route2.Shard, "workflow %s should assign to same shard", wf)
129-
}
125+
// Same workflows → same shards
126+
for wf, route1 := range outcomeProto.Routes {
127+
route2, exists := outcomeProto2.Routes[wf]
128+
require.True(t, exists)
129+
require.Equal(t, route1.Shard, route2.Shard, "workflow %s should assign to same shard", wf)
130+
}
131+
})
130132
}
131133

132134
func TestPlugin_StateTransitions(t *testing.T) {

0 commit comments

Comments
 (0)