forked from Argus-Labs/world-engine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathworld_persona_test.go
162 lines (142 loc) · 5.76 KB
/
world_persona_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package cardinal_test
import (
"errors"
"fmt"
"testing"
"time"
"pkg.world.dev/world-engine/assert"
"pkg.world.dev/world-engine/cardinal"
"pkg.world.dev/world-engine/cardinal/persona/component"
"pkg.world.dev/world-engine/cardinal/persona/msg"
"pkg.world.dev/world-engine/cardinal/search/filter"
"pkg.world.dev/world-engine/cardinal/types"
"pkg.world.dev/world-engine/sign"
)
func TestGetSignerComponentForPersona(t *testing.T) {
tf := cardinal.NewTestFixture(t, nil)
world := tf.World
msgType, exists := world.GetMessageByFullName("persona.create-persona")
assert.True(t, exists)
personaTag := "tyler"
signer := "foobar"
createPersonaMsg := msg.CreatePersona{
PersonaTag: personaTag,
SignerAddress: signer,
}
world.AddTransaction(msgType.ID(), createPersonaMsg, &sign.Transaction{})
tf.DoTick()
sc, err := world.GetSignerComponentForPersona(personaTag)
assert.NilError(t, err)
assert.Equal(t, sc.PersonaTag, personaTag)
assert.Equal(t, sc.SignerAddress, signer)
notRealPersona := "nobody_important"
sc, err = world.GetSignerComponentForPersona(notRealPersona)
assert.ErrorContains(t, err, fmt.Sprintf("persona tag %q not found", notRealPersona))
assert.Nil(t, sc)
}
func TestCreatePersonaSystem_WithNoPersonaTagCreateTxs_TickShouldBeFast(t *testing.T) {
tf := cardinal.NewTestFixture(t, nil)
const trials = 100
startTime := time.Now()
// Collect a baseline average tick duration when there are no persona tags and nothing is going on
for i := 0; i < trials; i++ {
tf.DoTick()
}
baselineDuration := time.Since(startTime) / trials
msgType, exists := tf.World.GetMessageByFullName("persona.create-persona")
assert.True(t, exists)
// Create 100 persona tags and make sure they exist
for i := 0; i < 100; i++ {
createPersonaMsg := msg.CreatePersona{
PersonaTag: fmt.Sprintf("personatag%d", i),
SignerAddress: fmt.Sprintf("some-signer-%d", i),
}
tf.World.AddTransaction(msgType.ID(), createPersonaMsg, &sign.Transaction{})
tf.DoTick()
// Make sure the persona tag was actually added
receipts, err := tf.World.GetTransactionReceiptsForTick(tf.World.CurrentTick() - 1)
assert.NilError(t, err)
assert.Equal(t, 1, len(receipts))
assert.Equal(t, 0, len(receipts[0].Errs))
}
startTime = time.Now()
// Collect another average for ticks that have no persona tag registrations. These ticks should be similar
// in duration to the baseline.
for i := 0; i < trials; i++ {
tf.DoTick()
}
saturatedDuration := time.Since(startTime) / trials
slowdownRatio := float64(saturatedDuration) / float64(baselineDuration)
// Fail this test if the second batch of ticks is more than 5 times slower than the original
// batch of ticks. The previously registered persona tags should have no performance impact on these systems.
assert.True(t, slowdownRatio < 5, "ticks are much slower when many persona tags have been registered")
}
func TestCreatePersonaSystem_WhenCardinalIsRestarted_PersonaTagsAreStillRegistered(t *testing.T) {
tf := cardinal.NewTestFixture(t, nil)
type countPersonaTagsResult struct {
personaTags map[string]bool
err error
}
// This is a buffered channel so that the System that uses it doesn't block. It has to be drained
// after the DoTick call.
numOfPersonaTags := make(chan countPersonaTagsResult, 1)
// emitNumberOfPersonaTagsSystem is a system that finds all the registered persona tags and sends them
// across a channel.
emitNumberOfPersonaTagsSystem := func(wCtx cardinal.WorldContext) error {
result := countPersonaTagsResult{personaTags: map[string]bool{}}
err := cardinal.NewSearch().
Entity(filter.Exact(filter.Component[component.SignerComponent]())).
Each(wCtx, func(id types.EntityID) bool {
comp, err := cardinal.GetComponent[component.SignerComponent](wCtx, id)
result.err = errors.Join(result.err, err)
result.personaTags[comp.PersonaTag] = true
return true
})
result.err = errors.Join(result.err, err)
numOfPersonaTags <- result
return nil
}
assert.NilError(t, cardinal.RegisterSystems(tf.World, emitNumberOfPersonaTagsSystem))
msgType, exists := tf.World.GetMessageByFullName("persona.create-persona")
assert.True(t, exists)
// Register 10 persona tags. None of these should fail.
for i := 0; i < 10; i++ {
currPersonaTag := fmt.Sprintf("pt%d", i)
tf.World.AddTransaction(msgType.ID(), msg.CreatePersona{
PersonaTag: currPersonaTag,
SignerAddress: fmt.Sprintf("sa%d", i),
}, &sign.Transaction{})
tf.DoTick()
result := <-numOfPersonaTags
assert.NilError(t, result.err)
assert.Equal(t, i+1, len(result.personaTags))
assert.True(t, result.personaTags[currPersonaTag])
}
// There should now be 10 persona tags registered.
// Simulate a cardinal restart by creating a new test fixture with the same redis DB.
tf = cardinal.NewTestFixture(t, tf.Redis)
assert.NilError(t, cardinal.RegisterSystems(tf.World, emitNumberOfPersonaTagsSystem))
// Make sure there are still 10 persona tags registered.
tf.DoTick()
result := <-numOfPersonaTags
assert.NilError(t, result.err)
assert.Equal(t, 10, len(result.personaTags))
for i := 0; i < 10; i++ {
currPersonaTag := fmt.Sprintf("pt%d", i)
assert.True(t, result.personaTags[currPersonaTag])
}
// This persona tag has already been registered, so it should fail to register this time.
repeatPersonaTag := "pt5"
tf.World.AddTransaction(msgType.ID(), msg.CreatePersona{
PersonaTag: repeatPersonaTag,
SignerAddress: "some-sa",
}, &sign.Transaction{})
tf.DoTick()
// Make sure the receipt from the previous tick talks about the failed persona tag registration.
receipts, err := tf.World.GetTransactionReceiptsForTick(tf.World.CurrentTick() - 1)
assert.NilError(t, err)
assert.Len(t, receipts, 1)
errs := receipts[0].Errs
assert.Len(t, errs, 1)
assert.ErrorContains(t, errs[0], "persona tag pt5 has already been registered")
}