def test_losers_advantage(client): """ user with the lose_count of 3 and others with that of 0 attempt to apply a lottery test loser is more likely to win target_url: /lotteries/<id>/draw """ users_num = 12 idx = 1 win_count = {i: 0 for i in range(1, users_num + 1)} # user.id -> count with client.application.app_context(): target_lottery = Lottery.query.get(idx) index = target_lottery.index users = User.query.order_by(User.id).all()[:users_num] users[0].lose_count = 3 user0_id = users[0].id add_db(users2application(users, target_lottery)) token = get_token(client, admin) resp = draw(client, token, idx, index) for winner_json in resp.get_json(): winner_id = winner_json['id'] win_count[winner_id] += 1 # display info when this test fails print("final results of applications (1's lose_count == 3)") print(win_count) assert win_count[user0_id] > 0
def test_draw(client): """attempt to draw a lottery 1. make some applications to one lottery 2. draws the lottery 3. test: status code 4. test: DB is changed target_url: /lotteries/<id>/draw [POST] """ idx = 1 with client.application.app_context(): target_lottery = Lottery.query.get(idx) index = target_lottery.index users = User.query.all() add_db(user2application(user, target_lottery) for user in users) token = get_token(client, admin) resp = draw(client, token, idx, index) assert resp.status_code == 200 winners_id = [winner['id'] for winner in resp.get_json()] users = User.query.all() target_lottery = Lottery.query.get(idx) waiting_cnt = 0 for user in users: application = get_application(user, target_lottery) if user.id in winners_id: assert application.status == 'won' assert user.win_count == 1 assert user.lose_count == 0 assert user.waiting_count == 0 else: assert application.status in {'lose', 'waiting'} assert user.win_count == 0 if application.status == 'waiting': assert user.lose_count == 0 assert user.waiting_count == 1 waiting_cnt += 1 else: assert user.lose_count == 1 assert user.waiting_count == 0 assert waiting_cnt == 3
def test_draw_lots_of_groups_and_normal(client): """attempt to draw a lottery as 2 groups of 2 members and 2 normal while WINNERS_NUM is 5 1. make some applications to one lottery as groups 2. draws the lottery 3. test: status code 4. test: DB is changed 5. test: result of each member 6. test: number of winners is less than 3 target_url: /lotteries/<id>/draw [POST] """ idx = 1 members = (0, 1) reps = (2, 3) normals = (4, 5) with client.application.app_context(): target_lottery = Lottery.query.get(idx) index = target_lottery.index users = User.query.all() member_apps = [user2application(users[i], target_lottery) for i in chain(members, normals)] add_db(member_apps) rep_apps = [rep2application(users[rep], target_lottery, [member_apps[member]]) for rep, member in zip(reps, members)] add_db(rep_apps) token = get_token(client, admin) resp = draw(client, token, idx, index) assert resp.status_code == 200 winners = resp.get_json() assert len(winners) == 5 # client.application.config['WINNERS_NUM'] users = User.query.all() target_lottery = Lottery.query.get(idx) for rep, member in zip(reps, members): rep_status = get_application(users[rep], target_lottery).status member_status = \ get_application(users[member], target_lottery).status assert rep_status == member_status
def test_draw_group(client): """attempt to draw a lottery as a group 1. make some applications to one lottery as a group 2. draws the lottery 3. test: status code 4. test: DB is changed 5. test: result of each member (win) target_url: /lotteries/<id>/draw [POST] """ idx = 1 group_size = 3 with client.application.app_context(): target_lottery = Lottery.query.get(idx) index = target_lottery.index users = User.query.all() members_app = [user2application(user, target_lottery) for user in users[1:group_size]] add_db(members_app) rep_application = user2application( users[0], target_lottery, is_rep=True, group_members=apps2members(members_app)) add_db((rep_application,)) # 1-element tuple token = get_token(client, admin) resp = draw(client, token, idx, index) assert resp.status_code == 200 users = User.query.all() target_lottery = Lottery.query.get(idx) rep_status = get_application(users[0], target_lottery).status assert rep_status == "won" assert users[0].win_count == 1 for user in users[1:group_size]: application = get_application(user, target_lottery) assert application.status == "won" assert user.win_count == 1
def test_apply_member_consecutive(client): """attempt to apply after a member's previous won / lose / waiting test: win -> refused (because he/she should be watching a show) test: lose / waiting -> accepted target_url: /lotteries/<id> [POST] """ idx1 = 1 token_admin = get_token(client, admin) with client.application.app_context(): lottery1 = Lottery.query.get(idx1) index1 = lottery1.index lottery2 = Lottery.query.filter_by( classroom_id=lottery1.classroom_id, index=lottery1.index + 1).one() idx2 = lottery2.id index2 = lottery2.index # 5 won, 2 lose, 3 waiting users = User.query.filter_by(authority='normal').limit(10).all() apps = users2application(users, lottery1) add_db(apps) draw_all(client, token_admin, index=index1) people = [Application.query.filter_by(status=s).first().user for s in ('won', 'lose', 'waiting')] sids = [person.secret_id for person in people] tokens = [login(client, person.secret_id, '')['token'] for person in people] for i, (token_i, member_i) in enumerate(((0, 1), (2, 0), (1, 2))): with mock.patch('api.routes.api.get_time_index', return_value=index2): resp = post(client, f'/lotteries/{idx2}', token=tokens[token_i], group_members=[sids[member_i]]) if i == 2: assert resp.status_code == 200 else: assert resp.status_code == 403 assert 'while watching' in resp.get_json()['message']
def test_apply_consecutive(client): """attempt to apply after previous won / lose / waiting test: win -> refused (because he/she should be watching a show) test: lose / waiting -> accepted target_url: /lotteries/<id> [POST] """ idx1 = 1 token_admin = get_token(client, admin) with client.application.app_context(): lottery1 = Lottery.query.get(idx1) index1 = lottery1.index lottery2 = Lottery.query.filter_by( classroom_id=lottery1.classroom_id, index=lottery1.index + 1).one() idx2 = lottery2.id index2 = lottery2.index # 5 won, 2 lose, 3 waiting users = User.query.filter_by(authority='normal').limit(10).all() apps = users2application(users, lottery1) add_db(apps) user_sids = [user.secret_id for user in users] app_ids = [app.id for app in apps] draw_all(client, token_admin, index=index1) for user_sid, app_id in zip(user_sids, app_ids): app_after = Application.query.get(app_id) token = login(client, user_sid, '')['token'] with mock.patch('api.routes.api.get_time_index', return_value=index2): resp = post(client, f'/lotteries/{idx2}', token=token, group_members=[]) if app_after.status == 'won': assert resp.status_code == 403 assert 'while watching a show' in resp.get_json()['message'] else: assert resp.status_code == 200
def test_get_allapplications(client): """test proper infomation is returned from the API to a normal user target_url: /applications """ with client.application.app_context(): lottery = Lottery.query.get(1) user = User.query.filter_by(secret_id=test_user['secret_id']).one() apps = [user2application(user, lottery) for _ in range(2)] apps[1].created_on += datetime.timedelta(days=-1) add_db(apps) correct_resp = applications_schema.dump([apps[0]])[0] resp = as_user_get(client, test_user['secret_id'], test_user['g-recaptcha-response'], '/applications') assert resp.get_json() == correct_resp
def test_draw_lots_of_groups(client): """attempt to draw a lottery as 3 groups of 2 members and 2 group of 3 members while WINNERS_NUM is 5 and WAITING_NUM is 3 1. make some applications to one lottery as groups 2. draws the lottery 3. test: status code 4. test: DB is changed 5. test: result of each member 6. test: number of winners is 5 (*not 4*) 7. test: size of waiting list < 3 target_url: /lotteries/<id>/draw [POST] """ idx = 1 groups = {0: [1], 2: [3], 4: [5, 6], 7: [8, 9]} # rep -> members with client.application.app_context(): target_lottery = Lottery.query.get(idx) index = target_lottery.index users = User.query.all() for rep, members in groups.items(): members_app = [user2application(users[i], target_lottery) for i in members] add_db(members_app) rep_app = rep2application(users[rep], target_lottery, apps2members(members_app)) add_db([rep_app]) token = get_token(client, admin) resp = draw(client, token, idx, index) assert resp.status_code == 200 winners = resp.get_json() assert len(winners) == 5 users = User.query.all() target_lottery = Lottery.query.get(idx) won_cnt = 0 lose_cnt = 0 waiting_cnt = 0 for rep, members in groups.items(): rep_status = get_application(users[rep], target_lottery).status members_status = (get_application(users[i], target_lottery).status for i in members) assert all(status == rep_status for status in members_status) if rep_status == "won": won_cnt += 1 + len(members) elif rep_status == "lose": lose_cnt += 1 + len(members) else: # make sure "waiting-pending" does not leak out assert rep_status == "waiting" waiting_cnt += 1 + len(members) assert won_cnt == 5 assert lose_cnt in {2, 3} assert waiting_cnt in {3, 2} assert lose_cnt + waiting_cnt == 5