Skip to content

Commit 0303c9f

Browse files
committed
test: cover boot path character creation
1 parent 4c331f2 commit 0303c9f

2 files changed

Lines changed: 225 additions & 0 deletions

File tree

internal/boot/flow_socket_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,104 @@ func TestBootFlowEntersGameOverTCP(t *testing.T) {
176176
t.Fatalf("expected server phase %q, got %q", session.PhaseGame, got)
177177
}
178178
}
179+
180+
func TestBootFlowCreatesCharacterAndEntersGameOverTCP(t *testing.T) {
181+
server := startBootTestServer(t, testConfig())
182+
client := newBootTestClient(t, server.address())
183+
184+
challenge := client.readFrame(t)
185+
wantChallenge := control.EncodeKeyChallenge(testConfig().Handshake.KeyChallenge)
186+
if !bytes.Equal(challenge.Raw, wantChallenge) {
187+
t.Fatalf("unexpected key challenge bytes: got %x want %x", challenge.Raw, wantChallenge)
188+
}
189+
client.writeFrame(t, control.EncodeKeyResponse(control.KeyResponsePacket{
190+
ClientPublicKey: sequentialBytes32(0x40),
191+
ChallengeResponse: sequentialBytes32(0x60),
192+
}))
193+
complete := client.readFrame(t)
194+
wantComplete := control.EncodeKeyComplete(testConfig().Handshake.KeyComplete)
195+
if !bytes.Equal(complete.Raw, wantComplete) {
196+
t.Fatalf("unexpected key complete bytes: got %x want %x", complete.Raw, wantComplete)
197+
}
198+
phaseLogin := client.readFrame(t)
199+
wantPhaseLogin, err := control.EncodePhase(session.PhaseLogin)
200+
if err != nil {
201+
t.Fatalf("unexpected phase encode error: %v", err)
202+
}
203+
if !bytes.Equal(phaseLogin.Raw, wantPhaseLogin) {
204+
t.Fatalf("unexpected login phase bytes: got %x want %x", phaseLogin.Raw, wantPhaseLogin)
205+
}
206+
login2Raw, err := loginproto.EncodeLogin2(loginproto.Login2Packet{Login: "mkmk", LoginKey: 0x01020304})
207+
if err != nil {
208+
t.Fatalf("unexpected login2 encode error: %v", err)
209+
}
210+
client.writeFrame(t, login2Raw)
211+
if empire := client.readFrame(t); !bytes.Equal(empire.Raw, loginproto.EncodeEmpire(loginproto.EmpirePacket{Empire: 2})) {
212+
t.Fatalf("unexpected empire bytes: got %x", empire.Raw)
213+
}
214+
phaseSelect := client.readFrame(t)
215+
wantPhaseSelect, err := control.EncodePhase(session.PhaseSelect)
216+
if err != nil {
217+
t.Fatalf("unexpected phase encode error: %v", err)
218+
}
219+
if !bytes.Equal(phaseSelect.Raw, wantPhaseSelect) {
220+
t.Fatalf("unexpected select phase bytes: got %x want %x", phaseSelect.Raw, wantPhaseSelect)
221+
}
222+
loginSuccess := client.readFrame(t)
223+
wantSuccess, err := loginproto.EncodeLoginSuccess4(sampleLoginSuccessPacket())
224+
if err != nil {
225+
t.Fatalf("unexpected login success encode error: %v", err)
226+
}
227+
if !bytes.Equal(loginSuccess.Raw, wantSuccess) {
228+
t.Fatalf("unexpected login success bytes: got %x want %x", loginSuccess.Raw, wantSuccess)
229+
}
230+
231+
createRaw, err := worldproto.EncodeCharacterCreate(worldproto.CharacterCreatePacket{Index: 2, Name: "FreshSura", RaceNum: 2, Shape: 1})
232+
if err != nil {
233+
t.Fatalf("unexpected create encode error: %v", err)
234+
}
235+
client.writeFrame(t, createRaw)
236+
createSuccess := client.readFrame(t)
237+
wantCreateSuccess, err := worldproto.EncodePlayerCreateSuccess(worldproto.PlayerCreateSuccessPacket{Index: 2, Player: sampleCreatedPlayer()})
238+
if err != nil {
239+
t.Fatalf("unexpected create success encode error: %v", err)
240+
}
241+
if !bytes.Equal(createSuccess.Raw, wantCreateSuccess) {
242+
t.Fatalf("unexpected create success bytes: got %x want %x", createSuccess.Raw, wantCreateSuccess)
243+
}
244+
245+
client.writeFrame(t, worldproto.EncodeCharacterSelect(worldproto.CharacterSelectPacket{Index: 2}))
246+
phaseLoading := client.readFrame(t)
247+
wantPhaseLoading, err := control.EncodePhase(session.PhaseLoading)
248+
if err != nil {
249+
t.Fatalf("unexpected loading phase encode error: %v", err)
250+
}
251+
if !bytes.Equal(phaseLoading.Raw, wantPhaseLoading) {
252+
t.Fatalf("unexpected loading phase bytes: got %x want %x", phaseLoading.Raw, wantPhaseLoading)
253+
}
254+
mainCharacter := client.readFrame(t)
255+
wantMainCharacter, err := worldproto.EncodeMainCharacter(sampleCreatedMainCharacter())
256+
if err != nil {
257+
t.Fatalf("unexpected created main character encode error: %v", err)
258+
}
259+
if !bytes.Equal(mainCharacter.Raw, wantMainCharacter) {
260+
t.Fatalf("unexpected created main character bytes: got %x want %x", mainCharacter.Raw, wantMainCharacter)
261+
}
262+
playerPoints := client.readFrame(t)
263+
wantPlayerPoints := worldproto.EncodePlayerPoints(sampleCreatedPlayerPoints())
264+
if !bytes.Equal(playerPoints.Raw, wantPlayerPoints) {
265+
t.Fatalf("unexpected created player points bytes: got %x want %x", playerPoints.Raw, wantPlayerPoints)
266+
}
267+
client.writeFrame(t, worldproto.EncodeEnterGame())
268+
phaseGame := client.readFrame(t)
269+
wantPhaseGame, err := control.EncodePhase(session.PhaseGame)
270+
if err != nil {
271+
t.Fatalf("unexpected game phase encode error: %v", err)
272+
}
273+
if !bytes.Equal(phaseGame.Raw, wantPhaseGame) {
274+
t.Fatalf("unexpected game phase bytes: got %x want %x", phaseGame.Raw, wantPhaseGame)
275+
}
276+
if got := server.currentPhase(); got != session.PhaseGame {
277+
t.Fatalf("expected server phase %q, got %q", session.PhaseGame, got)
278+
}
279+
}

internal/boot/flow_test.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,71 @@ func TestHandleClientFrameRoutesCharacterSelectAndEnterGameToGame(t *testing.T)
227227
}
228228
}
229229

230+
func TestHandleClientFrameRoutesCharacterCreateThenSelectToGame(t *testing.T) {
231+
flow := NewFlow(testConfig())
232+
233+
if _, err := flow.Start(); err != nil {
234+
t.Fatalf("unexpected start error: %v", err)
235+
}
236+
_, err := flow.HandleClientFrame(decodeSingleFrame(t, control.EncodeKeyResponse(control.KeyResponsePacket{
237+
ClientPublicKey: sequentialBytes32(0x40),
238+
ChallengeResponse: sequentialBytes32(0x60),
239+
})))
240+
if err != nil {
241+
t.Fatalf("unexpected handshake error: %v", err)
242+
}
243+
login2Raw, err := loginproto.EncodeLogin2(loginproto.Login2Packet{Login: "mkmk", LoginKey: 0x01020304})
244+
if err != nil {
245+
t.Fatalf("unexpected login2 encode error: %v", err)
246+
}
247+
_, err = flow.HandleClientFrame(decodeSingleFrame(t, login2Raw))
248+
if err != nil {
249+
t.Fatalf("unexpected login error: %v", err)
250+
}
251+
252+
createRaw, err := worldproto.EncodeCharacterCreate(worldproto.CharacterCreatePacket{Index: 2, Name: "FreshSura", RaceNum: 2, Shape: 1})
253+
if err != nil {
254+
t.Fatalf("unexpected create encode error: %v", err)
255+
}
256+
createOut, err := flow.HandleClientFrame(decodeSingleFrame(t, createRaw))
257+
if err != nil {
258+
t.Fatalf("unexpected character create error: %v", err)
259+
}
260+
wantCreate, err := worldproto.EncodePlayerCreateSuccess(worldproto.PlayerCreateSuccessPacket{Index: 2, Player: sampleCreatedPlayer()})
261+
if err != nil {
262+
t.Fatalf("unexpected create success encode error: %v", err)
263+
}
264+
if len(createOut) != 1 || !bytes.Equal(createOut[0], wantCreate) {
265+
t.Fatalf("unexpected create output: got %x want %x", createOut, wantCreate)
266+
}
267+
if flow.CurrentPhase() != session.PhaseSelect {
268+
t.Fatalf("expected phase %q after create, got %q", session.PhaseSelect, flow.CurrentPhase())
269+
}
270+
271+
selectOut, err := flow.HandleClientFrame(decodeSingleFrame(t, worldproto.EncodeCharacterSelect(worldproto.CharacterSelectPacket{Index: 2})))
272+
if err != nil {
273+
t.Fatalf("unexpected select after create error: %v", err)
274+
}
275+
wantPhaseLoading, err := control.EncodePhase(session.PhaseLoading)
276+
if err != nil {
277+
t.Fatalf("unexpected loading phase encode error: %v", err)
278+
}
279+
wantMain, err := worldproto.EncodeMainCharacter(sampleCreatedMainCharacter())
280+
if err != nil {
281+
t.Fatalf("unexpected created main character encode error: %v", err)
282+
}
283+
wantPoints := worldproto.EncodePlayerPoints(sampleCreatedPlayerPoints())
284+
wantSelect := [][]byte{wantPhaseLoading, wantMain, wantPoints}
285+
if len(selectOut) != len(wantSelect) {
286+
t.Fatalf("expected %d select frames, got %d", len(wantSelect), len(selectOut))
287+
}
288+
for i := range wantSelect {
289+
if !bytes.Equal(selectOut[i], wantSelect[i]) {
290+
t.Fatalf("unexpected created select frame %d: got %x want %x", i, selectOut[i], wantSelect[i])
291+
}
292+
}
293+
}
294+
230295
func decodeSingleFrame(t *testing.T, raw []byte) frame.Frame {
231296
t.Helper()
232297

@@ -270,7 +335,20 @@ func testConfig() Config {
270335
},
271336
},
272337
WorldEntry: worldentry.Config{
338+
CreateCharacter: func(packet worldproto.CharacterCreatePacket) worldentry.CreateResult {
339+
if packet.Index != 2 || packet.Name != "FreshSura" || packet.RaceNum != 2 || packet.Shape != 1 {
340+
return worldentry.CreateResult{Accepted: false, FailureType: 0}
341+
}
342+
return worldentry.CreateResult{Accepted: true, Player: worldproto.PlayerCreateSuccessPacket{Index: 2, Player: sampleCreatedPlayer()}}
343+
},
273344
SelectCharacter: func(index uint8) worldentry.Result {
345+
if index == 2 {
346+
return worldentry.Result{
347+
Accepted: true,
348+
MainCharacter: sampleCreatedMainCharacter(),
349+
PlayerPoints: sampleCreatedPlayerPoints(),
350+
}
351+
}
274352
if index != 1 {
275353
return worldentry.Result{Accepted: false}
276354
}
@@ -371,6 +449,52 @@ func samplePlayerPoints() worldproto.PlayerPointsPacket {
371449
return points
372450
}
373451

452+
func sampleCreatedPlayer() loginproto.SimplePlayer {
453+
return loginproto.SimplePlayer{
454+
ID: 3,
455+
Name: "FreshSura",
456+
Job: 2,
457+
Level: 1,
458+
PlayMinutes: 0,
459+
ST: 5,
460+
HT: 3,
461+
DX: 3,
462+
IQ: 5,
463+
MainPart: 1,
464+
ChangeName: 0,
465+
HairPart: 0,
466+
Dummy: [4]byte{},
467+
X: 1200,
468+
Y: 2200,
469+
Addr: 0x0100007f,
470+
Port: 13000,
471+
SkillGroup: 0,
472+
}
473+
}
474+
475+
func sampleCreatedMainCharacter() worldproto.MainCharacterPacket {
476+
return worldproto.MainCharacterPacket{
477+
VID: 0x01020306,
478+
RaceNum: 2,
479+
Name: "FreshSura",
480+
BGMName: "",
481+
BGMVolume: 0,
482+
X: 1200,
483+
Y: 2200,
484+
Z: 0,
485+
Empire: 2,
486+
SkillGroup: 0,
487+
}
488+
}
489+
490+
func sampleCreatedPlayerPoints() worldproto.PlayerPointsPacket {
491+
var points worldproto.PlayerPointsPacket
492+
points.Points[0] = 1
493+
points.Points[1] = 650
494+
points.Points[2] = 200
495+
return points
496+
}
497+
374498
func sequentialBytes32(start byte) [32]byte {
375499
var out [32]byte
376500
for i := range out {

0 commit comments

Comments
 (0)