Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion HandleQueuedResults.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
import structures
from structures import global_dict, load_blob

def upload_setting(results, key):
# An upload without the setting means it is off. The client ends each upload
# with a line break, which stays on the last field.
return results.get(key, "").strip() == "YES"

def handle_queued_results():
out = []
results = json.loads(request.get_data(as_text=True))
Expand Down Expand Up @@ -44,6 +49,8 @@ def handle_queued_results():
Name=rumble, Rounds=int(results["rounds"]),
Field=results["field"], Melee=results["melee"] == "YES",
Teams=results["teams"] == "YES", TotalUploads=0,
HideNames=upload_setting(results, "hidenames"),
ClearData=upload_setting(results, "cleardata"),
MeleeSize=10)
out.append("CREATED NEW GAME TYPE " + rumble + "\n")
logging.info("Created new game type: " + rumble)
Expand All @@ -52,7 +59,9 @@ def handle_queued_results():
rounds = (game.Rounds == int(results["rounds"]))
teams = game.Teams == (results["teams"] == "YES")
melee = game.Melee == (results["melee"] == "YES")
allowed = field and rounds and teams and melee
hidenames = game.HideNames == upload_setting(results, "hidenames")
cleardata = game.ClearData == upload_setting(results, "cleardata")
allowed = field and rounds and teams and melee and hidenames and cleardata
if not allowed:
errstr = "OK. ERROR. Incorrect " + rumble + " config: "
errorReasons = []
Expand All @@ -64,6 +73,10 @@ def handle_queued_results():
errorReasons.append("teams ")
if not melee:
errorReasons.append("melee ")
if not hidenames:
errorReasons.append("hidenames ")
if not cleardata:
errorReasons.append("cleardata ")
logging.error(errstr + ", ".join(errorReasons) + " User: " + results["user"])
return "".join(out)

Expand Down
4 changes: 3 additions & 1 deletion structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def load_blob(blob, default):
total = "TOTAL"
participants = "PARTICIPANTS"
sync = "SYNCHRONIZE"
allowed_clients = ["1.11.2"]
allowed_clients = ["1.11.2", "1.12.0"]
allowed_versions = ["1"]

global_dict = {}
Expand Down Expand Up @@ -130,6 +130,8 @@ class Rumble(db.Model):
MeleeSize = db.IntegerProperty(indexed = False)
Rounds = db.IntegerProperty(indexed = False)
Field = db.StringProperty(indexed = False)
HideNames = db.BooleanProperty(indexed = False, default = False)
ClearData = db.BooleanProperty(indexed = False, default = False)
Name = db.StringProperty(indexed = False) # key_name
TotalUploads = db.IntegerProperty(indexed = False)
Participants = db.StringListProperty(indexed = False)
Expand Down
69 changes: 64 additions & 5 deletions test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import wsgi_local # noqa: E402 (imports gae_shim first, starts background threads)
import background # noqa: E402
import store # noqa: E402
import structures # noqa: E402
from google.appengine.api import taskqueue # noqa: E402 (the shim)

Expand All @@ -28,10 +29,10 @@
GAME = "TestRumble"


def make_battle(fname, sname, fscore, sscore):
def make_battle(fname, sname, fscore, sscore, game=GAME, settings=""):
"""A minimal valid /UploadedResults body (a 1v1 battle, A-vs-B)."""
fields = {
"client": "1.11.2", "version": "1", "game": GAME,
"client": "1.12.0", "version": "1", "game": game,
"rounds": "35", "field": "1000x1000", "melee": "NO", "teams": "NO",
"fname": fname, "sname": sname,
"fscore": str(fscore), "sscore": str(sscore),
Expand All @@ -40,17 +41,25 @@ def make_battle(fname, sname, fscore, sscore):
"ssurvival": "0" if fscore >= sscore else "35",
"user": "tester", "time": str(int(time.time() * 1000)),
}
return "&".join("%s=%s" % kv for kv in fields.items())
return "&".join("%s=%s" % kv for kv in fields.items()) + settings


def upload(fname, sname, fscore, sscore):
r = client.post("/UploadedResults", data=make_battle(fname, sname, fscore, sscore))
def upload(fname, sname, fscore, sscore, game=GAME, settings=""):
r = client.post("/UploadedResults", data=make_battle(fname, sname, fscore, sscore, game, settings))
body = r.get_data(as_text=True)
assert r.status_code == 200 and "OK" in body, (r.status_code, body)
assert "added to queue" in body, "upload not accepted: " + body
return body


def battles(game):
"""The battles of the Alpha-Bravo pairing, which unlike a bot's total never drops when an opponent retires."""
for pairing in store.load_pairings(game, "Alpha"):
if pairing.Name == "Bravo":
return int(pairing.Battles)
return 0


def get_json(path):
r = client.get(path)
assert r.status_code == 200, (path, r.status_code)
Expand Down Expand Up @@ -277,6 +286,56 @@ def first_bot(path):
assert without_header == 403, without_header
assert with_header == 200, with_header

# === Scenario: a rumble stored before these settings existed has them off ===
# GIVEN a stored rumble without the settings
# WHEN it is read
old = structures.Rumble._from_row("OldRumble", {"Name": "OldRumble"})
# THEN both settings are off
assert old.HideNames is False and old.ClearData is False, old

# === Scenario: an upload without the settings works as before ===
# GIVEN a rumble with the settings off
before = battles(GAME)
# WHEN an upload without the settings arrives
upload("Alpha", "Bravo", 60, 40)
background.drain()
# THEN it counts
assert battles(GAME) == before + 1, battles(GAME)

# === Scenario: a rumble with the settings off rejects results with them on ===
# GIVEN the same rumble
before = battles(GAME)
# WHEN uploads with either setting on arrive, the first as the client sends it
upload("Alpha", "Bravo", 60, 40, settings="&hidenames=YES\n")
upload("Alpha", "Bravo", 60, 40, settings="&cleardata=YES")
background.drain()
# THEN neither counts
assert battles(GAME) == before, battles(GAME)

# === Scenario: a new rumble takes the settings from its first upload ===
# GIVEN no rumble called HiddenRumble
# WHEN the first upload has both settings on, as the client sends it
both = "&cleardata=YES&hidenames=YES\r\n"
upload("Alpha", "Bravo", 60, 40, game="HiddenRumble", settings=both)
background.drain()
# THEN the rumble has them on, and the battle counts
hidden = structures.Rumble.get_by_key_name("HiddenRumble")
assert hidden.HideNames is True and hidden.ClearData is True, hidden
assert battles("HiddenRumble") == 1, battles("HiddenRumble")

# === Scenario: a rumble with the settings on only takes results with them on ===
# GIVEN that rumble
# WHEN uploads with no settings, or only one of them, arrive
upload("Alpha", "Bravo", 60, 40, game="HiddenRumble")
upload("Alpha", "Bravo", 60, 40, game="HiddenRumble", settings="&hidenames=YES\n")
upload("Alpha", "Bravo", 60, 40, game="HiddenRumble", settings="&cleardata=YES")
background.drain()
# THEN they do not count, but one with both on does
assert battles("HiddenRumble") == 1, battles("HiddenRumble")
upload("Alpha", "Bravo", 61, 39, game="HiddenRumble", settings=both)
background.drain()
assert battles("HiddenRumble") == 2, battles("HiddenRumble")

print("test_e2e OK")


Expand Down