Class: GamekeyReferenceTests

Inherits:
Object
  • Object
show all
Defined in:
lib/reference.rb

Overview

This class defines the reference tests for the Gamekey Service. Dart implementation must pass exactly the same test cases.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(host: Defaults::TESTHOST) ⇒ GamekeyReferenceTests

Constructor to create a Gamekey service.



19
20
21
22
23
24
25
26
27
28
# File 'lib/reference.rb', line 19

def initialize(host: Defaults::TESTHOST)
  @host = host

  @user = 'New One'
  @pwd = 'secret'

  @game = 'New Game'
  @secret = 'secret'

end

Instance Attribute Details

#hostObject (readonly)

Host to test



15
16
17
# File 'lib/reference.rb', line 15

def host
  @host
end

Instance Method Details

#checkUserGameStates(user, game, n) ⇒ Object

Checks that all gamestates stored can be listed.



789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
# File 'lib/reference.rb', line 789

def checkUserGameStates(user, game, n)
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  gameid = game['id']
  userid  = user['id']

  get_states = Net::HTTP::Get.new("/gamestate/#{gameid}/#{userid}")
  get_states.set_form_data({'secret' => 'xyz', 'pwd' => 'xyz'})


  res = http.request(get_states)
  return "#{error('GET', '/gamestate/gid/uid', "GUS-1")} Could not get gamestates for game id #{gameid} and userid '#{userid}',\n#{res.body}".red unless res.code == "200"

  states = JSON.parse(res.body)
  return "#{error('GET', '/gamestate/gid/uid', "GUS-2")} Expected to retrieve #{n} gamestates, got #{states.count}".red unless states.count == n

  state = states.shift
  while (state != nil)
    follower = states.shift
    if (follower != nil)
      return "#{error('GET', '/gamestate/gid/uid', "GUS-3")} Gamestates should be returned by decreasing creation order".red unless Time.parse(state['created']) > Time.parse(follower['created'])
    end
    state = follower
  end

  "Fine: Checked that gamestates are returned in decreasing creation timestamp order.".green

end

#checkUserPlays(user, games) ⇒ Object

Checks that a user having gamestates related to game should be indicated to play the game.



767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
# File 'lib/reference.rb', line 767

def checkUserPlays(user, games)
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  gameids = games.map { |g| g['id'] }
  userid  = user['id']

  get_states = Net::HTTP::Get.new("/user/#{userid}")
  get_states.set_form_data({'pwd' => 'xyz'})
  res = http.request(get_states)

  return "#{error('GET', '/user/id', "UP-1")} Could not get user id #{userid},\n#{res.body}".red unless res.code == "200"

  user = JSON.parse(res.body)
  return "#{error('GET', '/user/id', "UP-2")} Expected user #{userid} to play #{gameids}, received #{user['games']}".red unless (gameids - user['games']).empty? && (user['games'] - gameids).empty?

  "Fine: Checked that user #{userid} plays games #{gameids}.".green
end

#createGameObject

Checks that creating a game (POST /game) works as specified.



321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/reference.rb', line 321

def createGame

  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  # Check that game can not be created if secret is not provided.
  request = Net::HTTP::Post.new("/game")
  request.set_form_data({
      'name' => @game,
  })
  send = DateTime.now
  res = http.request(request)
  return "#{error('POST', '/game', "PG-0")} Could create game '#{@game}' (should return HTTP code 400 due to missing secret)".red if (res.code == "200")

  # Check that game can be created
  request = Net::HTTP::Post.new("/game")
  request.set_form_data({
      'name' => @game,
      'secret' => @secret
  })

  send = DateTime.now
  res = http.request(request)
  return "#{error('POST', '/game', "PG-1")} Could not create game '#{@game}' (should return HTTP code 200, was #{res.code})\n #{res.body}".red unless (res.code == "200")

  begin
    game = JSON.parse(res.body)
    return "#{error('POST', '/game', "PG-2")} Created game has wrong name. Should be '#{@game}', was #{game['name']}.".red unless game['name'] == @game
    return "#{error('POST', '/game', "PG-3")} Created game must have an id. Id was #{game['id']}.".red if game['id'] == nil

    signature = Auth::signature(game['id'], @pwd)
    return "#{error('POST', '/game', "PG-4")} Created game must have a valid signature. Should be '#{signature}' (was '#{game['signature']}')".red unless signature == game['signature']

    created = DateTime.iso8601(game['created'])
    return "#{error('POST', '/game', "PG-4")} Created game should have an ISO 8601 encoded creation timestamp.".red if created.to_time.to_i < send.to_time.to_i

    @gid = game['id']
  rescue
    return ([
        "#{error('POST', '/game', "PG-5")}",
        "POST on /game must return a valid JSON answer.",
        "",
        "---",
        "#{res.body}",
        "---",
        "",
        "This seems",
        "- no valid JSON",
        "- or creation timestamp is not ISO 8601 encoded."
    ] * "\n").red
  end

  "Fine: Create game works".green
end

#createUserObject

Checks, that creating a new user (POST /user) works as specified.



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
# File 'lib/reference.rb', line 41

def createUser

  uri = URI("#{@host}/user")
  send = DateTime.now

  res = Net::HTTP.post_form(uri, 'name' => @user)
  return "#{error('POST', '/user', "PU-0")} Could create user '#{@user}' without password (should return HTTP code 400, was #{res.code})".red unless (res.code == "400")

  res = Net::HTTP.post_form(uri, 'pwd' => 'secret')
  return "#{error('POST', '/user', "PU-0a")} Could create user without name (should return HTTP code 400, was #{res.code})".red unless (res.code == "400")

  res = Net::HTTP.post_form(uri, 'name' => @user, 'pwd' => @pwd)

  return "#{error('POST', '/user', "PU-1")} Could not create user '#{@user}' (should return HTTP code 200, was #{res.code})".red unless (res.code == "200")
  begin
    user = JSON.parse(res.body)
    return "#{error('POST', '/user', "PU-2")} Created user has wrong name. Should be '#{user}', was #{user['name']}.".red unless user['name'] == @user
    return "#{error('POST', '/user', "PU-3")} Created user must have an id. Id was #{user['id']}.".red if user['id'] == nil

    signature = Auth::signature(user['id'], @pwd)
    return "#{error('POST', '/user', "PU-4")} Created user must have a valid signature. Should be '#{signature}' (was '#{user['signature']}')".red unless signature == user['signature']

    created = DateTime.iso8601(user['created'])
    return "#{error('POST', '/user', "PU-5")} Created user should have an ISO 8601 encoded creation timestamp.".red if created.to_time.to_i < send.to_time.to_i

    @id = user['id']
  rescue
    return ([
        "#{error('POST', '/user', "PU-6")}",
        "POST on /register/user must return a valid JSON answer.",
        "",
        "---",
        "#{res.body}",
        "---",
        "",
        "This seems",
        "- no valid JSON",
        "- or creation timestamp is not ISO 8601 encoded."
    ] * "\n").red
  end

  "Fine: Create user works".green
end

#deleteGameObject

Checks that deleting a game (DELETE /game/<id>) works as specified.



499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
# File 'lib/reference.rb', line 499

def deleteGame
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  unauth_request = Net::HTTP::Delete.new("/game/#{@gid}")

  res = http.request(unauth_request)
  return "#{error('DELETE', '/game/id', "DG-1")} Only authenticated game should delete their game resource (code should be 401, was #{res.code})\n#{res.body}".red unless res.code == "401"

  auth_request = Net::HTTP::Delete.new("/game/#{@gid}")
  auth_request.set_form_data({
     "secret" => "new secret",
  })

  res = http.request(auth_request)
  return "#{error('DELETE', '/game/id', "DG-2")} Authenticated games should delete their game resource (code should be 200, was #{res.code})\n#{res.body}".red unless res.code == "200"

  auth_request = Net::HTTP::Delete.new("/game/#{@gid}")
  auth_request.set_form_data({
      "secret" => "new secret",
  })

  res = http.request(auth_request)
  return "#{error('DELETE', '/game/id', "DG-3")} Deletion of games should be idempotent (code should be 200, was #{res.code})\n#{res.body}".red unless res.code == "200"

  "Fine: Delete game works".green
end

#deleteGameEntity(game) ⇒ Object

Checks that deleting a game should delete all game related game states.



635
636
637
638
639
640
641
642
643
644
645
# File 'lib/reference.rb', line 635

def deleteGameEntity(game)
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  delete_game = Net::HTTP::Delete.new("/game/#{game['id']}")
  delete_game.set_form_data({ 'secret' => 'xyz' })
  res = http.request(delete_game)
  return "#{error('DELETE', '/game/id', "DELETETESTGAME-1")} Could not delete game '#{game['name']}',\n#{res.body}".red unless res.code == "200"
  "Fine: Deleted game '#{game['id']}' successfully.".green

end

#deleteUserObject

Checks that deleteing user data (DELETE /user/<id>) works as specified.



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/reference.rb', line 241

def deleteUser
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  unauth_request = Net::HTTP::Delete.new("/user/#{@id}")

  res = http.request(unauth_request)
  return "#{error('DELETE', '/user/id', "DU-1")} Only authenticated users should delete their user resource (code should be 401, was #{res.code})".red unless res.code == "401"

  auth_request = Net::HTTP::Delete.new("/user/#{@id}")
  auth_request.set_form_data({
     "pwd" => "new password",
  })

  res = http.request(auth_request)
  return "#{error('DELETE', '/user/id', "DU-2")} Authenticated users should delete their user resource (code should be 200, was #{res.code})".red unless res.code == "200"

  auth_request = Net::HTTP::Delete.new("/user/#{@id}")
  auth_request.set_form_data({
     "secret" => "new password",
  })

  res = http.request(auth_request)
  return "#{error('DELETE', '/user/id', "DU-3")} Deletion of users should be idempotent (code should be 200, was #{res.code})\n#{res.body}".red unless res.code == "200"

  "Fine: Delete user works".green
end

#deleteUserEntity(user) ⇒ Object

Checks that deleting a user should delete all user related game states.



650
651
652
653
654
655
656
657
658
659
# File 'lib/reference.rb', line 650

def deleteUserEntity(user)
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  delete_user = Net::HTTP::Delete.new("/user/#{user['id']}")
  delete_user.set_form_data({ 'pwd' => 'xyz' })
  res = http.request(delete_user)
  return "#{error('DELETE', '/user/id', "DELETETESTUSER-1")} Could not delete user '#{user['name']}',\n#{res.body}".red unless res.code == "200"
  "Fine: Deleted user '#{user['id']}' successfully.".green
end

#error(operation, resource, id) ⇒ Object

Generates a standardized error string for better identification of failed test cases.



33
34
35
# File 'lib/reference.rb', line 33

def error(operation, resource, id)
  "Testcase [#{id}] failed, #{operation} on #{resource}: "
end

#gameResourceHandlingObject

Groups all user resource related test cases.



566
567
568
569
570
571
572
573
574
# File 'lib/reference.rb', line 566

def gameResourceHandling
  puts "Checking game resource handling"
  puts createGame
  puts listGames
  puts readGame
  puts updateGame
  puts deleteGame
  puts stressGame
end

#gamestateResourceHandlingObject

Groups all gamestate resource related test cases.



822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
# File 'lib/reference.rb', line 822

def gamestateResourceHandling

  users = prepareUsers
  games = prepareGames

  puts "Checking gamestate resource handling"
  puts storeGamestate(games[0], users[0], 3, Defaults::TESTLIST)
  puts storeGamestate(games[1], users[0], 2, Defaults::TESTHASH)
  puts storeGamestate(games[1], users[1], 1, Defaults::TESTHASH)

  puts checkUserGameStates(users[0], games[0], 3)
  puts checkUserGameStates(users[0], games[1], 2)
  puts checkUserGameStates(users[1], games[1], 1)

  puts listGameStates(games[0], users[0], 3)
  puts listGameStates(games[1], users[0], 2)
  puts listGameStates(games[1], users[1], 1)
  puts listGameStates(games[2], users[2], 0)

  puts checkUserPlays(users[0], [games[0], games[1]])
  puts checkUserPlays(users[1], [games[1]])
  puts checkUserPlays(users[2], [])

  puts deleteGameEntity(games[2])

  puts checkUserPlays(users[0], [games[0], games[1]])
  puts checkUserPlays(users[1], [games[1]])
  puts checkUserPlays(users[2], [])

  puts deleteUserEntity(users[2])

  puts checkUserPlays(users[0], [games[0], games[1]])
  puts checkUserPlays(users[1], [games[1]])

  puts deleteGameEntity(games[1])

  puts checkUserPlays(users[0], [games[0]])
  puts checkUserPlays(users[1], [])

  puts deleteGameEntity(games[0])
  puts checkUserPlays(users[0], [])
  puts checkUserPlays(users[1], [])

  puts deleteUserEntity(users[1])
  puts deleteUserEntity(users[0])

end

#listGamesObject

Checks that listing all games (GET /games) works as specified.



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
# File 'lib/reference.rb', line 379

def listGames
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)
  request = Net::HTTP::Get.new("/games")

  res = http.request(request)

  begin

    games = JSON.parse(res.body)

    return "#{error('GET', '/games', "GG-1")} Only games should be returned.".red unless games.all? { |g| g['type'].downcase == 'game' }
    return "#{error('GET', '/games', "GG-2")} Each game should have a name.".red unless games.all? { |g| g['name'] != nil }
    return "#{error('GET', '/games', "GG-3")} Each game should have a id.".red unless games.all? { |g| g['id'] != nil }
    return "#{error('GET', '/games', "GG-4")} Each game should have a signature.".red unless games.all? { |g| g['signature'] != nil }
    return "#{error('GET', '/games', "GG-5")} No game should include users".red if games.any? { |g| g['users'] != nil }

  rescue
    return ([
        "#{error('GET', '/games', "GG-6")}",
        "List games did not return a valid JSON answer:",
        "#{res.body}"
    ] * "\n").red

  end
  "Fine: List games works".green
end

#listGameStates(game, user, n) ⇒ Object

Checks that stored game states of a user playing a game can be listed as intended.



723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
# File 'lib/reference.rb', line 723

def listGameStates(game, user, n)

  gameid = game['id']
  userid   = user['id']

  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  unauth_get_state = Net::HTTP::Get.new("/gamestate/#{gameid}/#{userid}")
  res = http.request(unauth_get_state)
  return "#{error('GET', '/gamestate/gid/uid', "GGS-1")} Getting game states should only work for authenticated games, code expected 401, was #{res.code},\n#{res.body}".red unless res.code == "401"

  get_state = Net::HTTP::Get.new("/gamestate/#{gameid}/#{userid}")
  get_state.set_form_data({ 'secret' => 'xyz' })

  res = http.request(get_state)
  return "#{error('GET', '/gamestate/gid/uid', "GGS-2")} Getting stored states should work for authenticated games, code expected 200, was #{res.code},\n#{res.body}".red unless res.code == "200"

  begin
    states = JSON.parse(res.body)

    return "#{error('GET', '/gamestate/gid/uid', "GGS-3")} Expected to retrieve #{n} gamestates, got #{states.count}".red unless states.count == n
    return "#{error('GET', '/gamestate/gid/uid', "GGS-4")} Only gamestates should be returned.".red unless states.all? { |u| u['type'].downcase == 'gamestate' }
    return "#{error('GET', '/gamestate/gid/uid', "GGS-5")} Each gamestate should have a gameid.".red unless states.all? { |u| u['gameid'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "GGS-6")} Each gamestate should contain the game name.".red unless states.all? { |u| u['gamename'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "GGS-7")} Each gamestate should have a userid.".red unless states.all? { |u| u['userid'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "GGS-8")} Each gamestate should contain the user name.".red unless states.all? { |u| u['username'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "GGS-9")} Each gamestate should have a creation timestamp.".red unless states.all? { |u| u['created'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "GGS-10")} Each gamestate should have a JSON encoded state.".red unless states.all? { |u| u['state'] != nil }

    now = Time.now.to_time.to_i
    return "#{error('GET', '/gamestate/gid/uid', "GGS-11")} Each gamestate should be created in the past and should be indicated by an ISO 8601 encoded timestamp.".red if states.any? { |u| DateTime.iso8601(u['created']).to_time.to_i > now }

  rescue Exception => ex
    return "#{error('GET', '/gamestate/gid/uid', "GGS-12")} Retrieved state was not JSON encoded,\n #{res.body}\n#{ex}".red
  end

  "Fine: Retrieved #{n} states successfully.".green

end

#listUsersObject

Checks that listing users (GET /users) works as specified.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/reference.rb', line 88

def listUsers
  uri = URI("#{@host}/users")
  res = Net::HTTP.get_response(uri)

  begin

    users = JSON.parse(res.body)

    return "#{error('GET', '/users', "GU-1")} Only users should be returned.".red unless users.all? { |u| u['type'].downcase == 'user' }
    return "#{error('GET', '/users', "GU-2")} Each user should have a name.".red unless users.all? { |u| u['name'] != nil }
    return "#{error('GET', '/users', "GU-3")} Each user should have a id.".red unless users.all? { |u| u['id'] != nil }
    return "#{error('GET', '/users', "GU-4")} Each user should have a signature.".red unless users.all? { |u| u['signature'] != nil }
    return "#{error('GET', '/users', "GU-5")} No user should include played games".red if users.any? { |u| u['games'] != nil }

  rescue
    return ([
        "#{error('GET', '/users', "GU-6")}",
        "List users did not return a valid JSON answer:",
        "#{res.body}"
    ] * "\n").red

  end
  "Fine: List users works".green
end

#prepareGamesObject

Helper routine to prepare some test games for game user resource relation tests.



608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
# File 'lib/reference.rb', line 608

def prepareGames
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  games = []

  3.times do |i|
    create_game = Net::HTTP::Post.new("/game")
    name = "Game #{i + 1}"
    create_game.set_form_data({
        'name' => name,
        'secret' => "xyz"
    })
    res = http.request(create_game)
    return "#{error('POST', '/user', "TESTGAME-1")} Could not create game '#{name}', #{res.body}".red unless res.code == "200"

    games << JSON.parse(res.body)

  end

  games

end

#prepareUsersObject

Helper routine to prepare some test users for game user resource relation tests.



580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
# File 'lib/reference.rb', line 580

def prepareUsers
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  users = []

  3.times do |i|
    create_user = Net::HTTP::Post.new("/user")
    name = "User #{i + 1}"
    create_user.set_form_data({
        'name' => name,
        'pwd' => "xyz"
    })
    res = http.request(create_user)
    return "#{error('POST', '/user', "TESTUSER-1")} Could not create user '#{name}', #{res.body}".red unless res.code == "200"

    users << JSON.parse(res.body)

  end

  users

end

#readGameObject

Checks that retrieving game data (GET /game/<id>) works as specified.



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
# File 'lib/reference.rb', line 410

def readGame
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)
  request = Net::HTTP::Get.new("/game/#{@gid}")
  res = http.request(request)

  return "#{error('GET', '/game/id', "GGI-1")} Only authenticated games should get game resource (code should be 401, was #{res.code})\n#{res.body}".red unless res.code == "401"

  request = Net::HTTP::Get.new("/game/#{@gid}")
  request.set_form_data({
      "secret" => "#{@secret}",
  })
  res = http.request(request)

  return "#{error('GET', '/game/id', "GGI-2")} Authenticated and registered games should get their game resource\n#{res.body}".red unless res.code == "200"

  begin

    game = JSON.parse(res.body)
    return "#{error('GET', '/game/id', "GGI-3")} Name should be '#{@game}', was '#{game['name']}'".red unless game['name'] == @game
    return "#{error('GET', '/game/id', "GGI-4")} Id should be '#{@id}', was '#{game['id']}'".red unless game['id'] == @gid
    return "#{error('GET', '/game/id', "GGI-5")} Type should be 'game', was '#{game['type']}'".red unless game['type'] == 'game'
    return "#{error('GET', '/game/id', "GGI-6")} Answer should contain users (ids) that played the game.\n#{game}".red if game['users'] == nil

  rescue
    return ([
        "#{error('GET', '/game/id', "GGI-7")}",
        "Get game did not return a valid JSON answer:",
        "#{res.body}"
    ] * "\n").red
  end

  "Fine: Read game works".green
end

#readUserObject

Checks that retrieving user data (GET /user/<id>) works as specified.



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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/reference.rb', line 116

def readUser

  # Check that users can queried by id

  uri = URI("#{@host}/user/#{@id}")
  res = Net::HTTP.get_response(uri)

  return "#{error('GET', '/user/id', "GUI-1")} Only authenticated users should get user resource (code should be 401, was #{res.code})\n#{res.body}".red unless res.code == "401"

  uri.query = URI.encode_www_form('id' => @id, 'pwd' => @pwd)
  res = Net::HTTP.get_response(uri)

  return "#{error('GET', '/user/id', "GUI-2")} Authenticated and registered user should get its personal user resource".red unless res.code == "200"

  begin

    user = JSON.parse(res.body)
    return "#{error('GET', '/user/id', "GUI-3")} Name should be '#{@user}', was '#{user['name']}'".red unless user['name'] == @user
    return "#{error('GET', '/user/id', "GUI-4")} Id should be '#{@id}', was '#{user['id']}'".red unless user['id'] == @id
    return "#{error('GET', '/user/id', "GUI-5")} Type should be 'user', was '#{user['type']}'".red unless user['type'] == 'user'
    return "#{error('GET', '/user/id', "GUI-6")} Answer should contain played games (ids)".red if user['games'] == nil

  rescue
    return ([
        "#{error('GET', '/user/id', "GUI-7")}",
        "Get user did not return a valid JSON answer:",
        "#{res.body}"
    ] * "\n").red
  end

  # Check that users can queried by name (name must be URI encoded)

  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  request = Net::HTTP::Get.new("/user/#{URI.encode(@user)}")
  request.set_form_data({
      "pwd" => "#{@pwd}",
      'byname' => 'wrong'
  })
  res = http.request(request)
  return "#{error('GET', '/user/name', "GUI-8")} wrong byname parameter should end in status code 400 (Bad Request), was #{res.code}".red unless res.code == "400"

  request = Net::HTTP::Get.new("/user/#{URI.encode(@user)}")
  request.set_form_data({
      "pwd" => "#{@pwd}",
      'byname' => 'true'
  })
  res = http.request(request)
  begin

    user = JSON.parse(res.body)
    return "#{error('GET', '/user/name', "GUI-9")} Name should be '#{@user}', was '#{user['name']}'".red unless user['name'] == @user
    return "#{error('GET', '/user/name', "GUI-10")} Id should be '#{@id}', was '#{user['id']}'".red unless user['id'] == @id
    return "#{error('GET', '/user/name', "GUI-11")} Type should be 'user', was '#{user['type']}'".red unless user['type'] == 'user'
    return "#{error('GET', '/user/name', "GUI-12")} Answer should contain played games (ids)".red if user['games'] == nil

  rescue
    return ([
        "#{error('GET', '/user/name', "GUI-13")}",
        "Get user did not return a valid JSON answer:",
        "#{res.body}"
    ] * "\n").red
  end


  "Fine: Read user works".green

end

#storeGamestate(game, user, n, state) ⇒ Object

Checks that storing game states of a user playing a game works as intended.



664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
# File 'lib/reference.rb', line 664

def storeGamestate(game, user, n, state)
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  gameid = game['id']
  userid = user['id']

  unauth_store_state = Net::HTTP::Post.new("/gamestate/#{gameid}/#{userid}")
  unauth_store_state.set_form_data({
      'state' => JSON.pretty_generate(state)
  })
  res = http.request(unauth_store_state)
  return "#{error('POST', '/gamestate/gid/uid', "PGS-1")} Store a state should only work for authenticated games, code expected 401, was #{res.code},\n#{res.body}".red unless res.code == "401"

  store_state = Net::HTTP::Post.new("/gamestate/#{gameid}/#{userid}")
  store_state.set_form_data({
      'secret' => 'xyz' ,
      'state' => JSON.pretty_generate(state)
  })

  n.times do
    res = http.request(store_state)
    return "#{error('POST', '/gamestate/gid/uid', "PGS-2")} Could not store state for game '#{gameid}' and user '#{userid}',\n#{res.body}".red unless res.code == "200"
  end

  unauth_get_states = Net::HTTP::Get.new("/gamestate/#{gameid}/#{userid}")
  res = http.request(unauth_get_states)
  return "#{error('GET', '/gamestate/gid/uid', "PGS-3")} Getting a state should only work for authenticated games, code expected 401, was #{res.code},\n#{res.body}".red unless res.code == "401"

  get_states = Net::HTTP::Get.new("/gamestate/#{gameid}/#{userid}")
  get_states.set_form_data({'secret' => 'xyz'})
  res = http.request(get_states)
  return "#{error('GET', '/gamestate/gid/uid', "PGS-4")} Getting stored states should work for authenticated games, code expected 200, was #{res.code},\n#{res.body}".red unless res.code == "200"

  begin
    states = JSON.parse(res.body)

    return "#{error('GET', '/gamestate/gid/uid', "PGS-5")} Expected to retrieve #{n} gamestates, got #{states.count}".red unless states.count == n
    return "#{error('GET', '/gamestate/gid/uid', "PGS-6")} Only gamestates should be returned.".red unless states.all? { |u| u['type'].downcase == 'gamestate' }
    return "#{error('GET', '/gamestate/gid/uid', "PGS-7")} Each gamestate should have a gameid.".red unless states.all? { |u| u['gameid'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "PGS-8")} Each gamestate should contain the game name.".red unless states.all? { |u| u['gamename'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "PGS-9")} Each gamestate should have a userid.".red unless states.all? { |u| u['userid'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "PGS-10")} Each gamestate should contain the user name.".red unless states.all? { |u| u['username'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "PGS-11")} Each gamestate should have a creation timestamp.".red unless states.all? { |u| u['created'] != nil }
    return "#{error('GET', '/gamestate/gid/uid', "PGS-12")} Each gamestate should have a JSON encoded state.".red unless states.all? { |u| u['state'] != nil }

    now = Time.now.to_time.to_i
    return "#{error('GET', '/gamestate/gid/uid', "PGS-13")} Each gamestate should be created in the past and should be indicated by an ISO 8601 encoded timestamp.".red if states.any? { |u| DateTime.iso8601(u['created']).to_time.to_i > now }

  rescue Exception => ex
    return "#{error('GET', '/gamestate/gid/uid', "PGS-14")} Retrieved state was not JSON encoded,\n #{res.body}\n#{ex}".red
  end

  "Fine: Stored #{n} states successfully.".green
end

#stressGameObject

Performs some stress tests on game resources.



530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
# File 'lib/reference.rb', line 530

def stressGame
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  1000.times do |i|
    request = Net::HTTP::Post.new("/game")
    name = "A Cool Game, #{i}th Edition"
    request.set_form_data({
        "name" => name,
        "secret" => "secret"
    })
    res = http.request(request)
    return "#{error('POST', '/game', "SG-1")} Creating game with name '#{name}' failed while stress testing.\n#{res.body}".red unless res.code == "200"
  end

  list_games = Net::HTTP::Get.new("/games")
  res = http.request(list_games);
  games = JSON.parse(res.body)

  return "#{error('GET', '/games', "SG-2")} Only #{games.count} games have been created. Should be 1000.".red unless games.count == 1000

  games.each do |game|
    delete_game = Net::HTTP::Delete.new("/game/#{game['id']}")
    delete_game.set_form_data({
        "secret" => "secret"
    })
    res = http.request(delete_game)
    return "#{error('DELETE', '/game/id', "SG-3")} Deleting game with id '#{game['name']} (#{game['id']})' failed while stress testing.\n#{res.body}".red unless res.code == "200"
  end

  "Fine: Stress testing of game resources works".green
end

#stressUserObject

Performs some stress tests on user resources.



272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/reference.rb', line 272

def stressUser
  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  1000.times do |i|
    request = Net::HTTP::Post.new("/user")
    name = "John Doe #{i}"
    request.set_form_data({
        "name" => name,
        "pwd" => "secret"
    })
    res = http.request(request)
    return "#{error('POST', '/user', "SU-1")} Creating user with name '#{name}' failed while stress testing.\n#{res.body}".red unless res.code == "200"
  end

  list_users = Net::HTTP::Get.new("/users")
  res = http.request(list_users);
  users = JSON.parse(res.body)

  return "#{error('GET', '/users', "SU-2")} #{users.count} users have been created. Should be 1000.".red unless users.count == 1000

  users.each do |user|
    delete_user = Net::HTTP::Delete.new("/user/#{user['id']}")
    delete_user.set_form_data({
        "pwd" => "secret"
    })
    res = http.request(delete_user)
    return "#{error('DELETE', '/user/id', "SU-3")} Deleting user with id '#{user['name']} (#{user['id']})' failed while stress testing.\n#{res.body}".red unless res.code == "200"
  end

  "Fine: Stress testing of user resources works".green
end

#updateGameObject

Checks that updating game data (PUT /game/<id>) works as specified.



448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
# File 'lib/reference.rb', line 448

def updateGame

  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  unauth_request = Net::HTTP::Put.new("/game/#{@gid}")
  unauth_request.set_form_data({
     "name" => "New Game Name",
  })

  res = http.request(unauth_request)
  return "#{error('PUT', '/game/id', "PUG-1")} Only authenticated games should update their game resource (code should be 401, was #{res.code})\n#{res.body}".red unless res.code == "401"

  new_name = "New Game Name"
  new_secret  = "new secret"
  new_url = "http://www.example.games/new+game+name"
  auth_request = Net::HTTP::Put.new("/game/#{@gid}")
  auth_request.set_form_data({
     "secret" => "#{@secret}",
     "name" => new_name,
     "url" => new_url,
     "newsecret" => new_secret
  })
  res = http.request(auth_request)

  begin
    game = JSON.parse(res.body)
    return "#{error('PUT', '/game/id', "PUG-2")} Name should be '#{new_name}', was '#{game['name']}'".red unless game['name'] == new_name
    return "#{error('PUT', '/game/id', "PUG-2")} Url should be '#{new_url}', was '#{game['url']}'".red unless game['url'] == new_url

    return "#{error('PUT', '/game/id', "PUG-3")} Id should be '#{@gid}', was '#{game['id']}'.".red unless game['id'] == @gid
    return "#{error('PUT', '/game/id', "PUG-4")} Type should be 'game', was '#{game['type']}'.".red unless game['type'] == 'game'
    return "#{error('PUT', '/game/id', "PUG-5")} Answer should contain no users (ids) that played the game.".red if game['users'] != nil
    return "#{error('PUT', '/game/id', "PUG-6")} Signature should be updated on secret change.".red unless Auth::authentic?(game, new_secret)

  rescue Exception => ex
    return ([
        "#{error('PUT', '/game/id', "PUG-7")}",
        "Update game did not return a valid JSON answer.",
        "Instead, we got exception: #{ex}",
        "#{res.body}"
    ] * "\n").red

  end

  "Fine: Update game works".green
end

#updateUserObject

Checks that updating user data (PUT /user/<id>) works as specified.



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/reference.rb', line 189

def updateUser

  uri = URI(@host)
  http = Net::HTTP.new(uri.host, uri.port)

  unauth_request = Net::HTTP::Put.new("/user/#{@id}")
  unauth_request.set_form_data({
      "name" => "New Name",
      "mail" => "[email protected]"
  })

  res = http.request(unauth_request)
  return "#{error('PUT', '/user/id', "PU-1")} Only authenticated users should update their user resource (code should be 401, was #{res.code})".red unless res.code == "401"

  new_name = "New Name"
  new_mail = "[email protected]"
  new_pwd  = "new password"
  auth_request = Net::HTTP::Put.new("/user/#{@id}")
  auth_request.set_form_data({
      "pwd" => "#{@pwd}",
      "name" => new_name,
      "mail" => new_mail,
      "newpwd" => new_pwd
  })
  res = http.request(auth_request)

  begin
    user = JSON.parse(res.body)
    return "#{error('PUT', '/user/id', "PU-2")} Name should be '#{new_name}', was '#{user['name']}'".red unless user['name'] == new_name
    return "#{error('PUT', '/user/id', "PU-3")} Mail should be '#{new_mail}', was '#{user['mail']}'".red unless user['mail'] == new_mail

    return "#{error('PUT', '/user/id', "PU-4")} Id should be '#{@id}', was '#{user['id']}'.".red unless user['id'] == @id
    return "#{error('PUT', '/user/id', "PU-5")} Type should be 'user', was '#{user['type']}'.".red unless user['type'] == 'user'
    return "#{error('PUT', '/user/id', "PU-6")} Answer should contain no played games (ids).".red if user['games'] != nil
    return "#{error('PUT', '/user/id', "PU-7")} Signature should be updated on password change.".red unless Auth::authentic?(user, new_pwd)

  rescue Exception => ex
    return ([
        "#{error('PUT', '/user/id', "PU-8")}",
        "Update user did not return a valid JSON answer.",
        "Instead, we got exception: #{ex}",
        "#{res.body}"
    ] * "\n").red

  end

  "Fine: Update user works".green
end

#userResourceHandlingObject

Groups all user resource related test cases.



308
309
310
311
312
313
314
315
316
# File 'lib/reference.rb', line 308

def userResourceHandling
  puts "Checking user resource handling"
  puts createUser
  puts listUsers
  puts readUser
  puts updateUser
  puts deleteUser
  puts stressUser
end