Example #1
0
def test_make_order():

    uid, token = next(token_gen)
    cart_id = new_cart(token)
    item_items = [next(item_gen)]

    # make order success
    res = make_order(uid, token, cart_id, item_items)
    assert res.status_code == 200
    order_id = res.json()["order_id"]
    assert len(order_id) > 0

    # verify query return the same order
    orders = json_get("/orders", token).json()
    assert len(orders) == 1
    q_order = orders[0]
    assert q_order["id"] == order_id
    assert q_order["items"] == item_items

    # verify order info correct
    _price = lambda i: item_store[i]["price"]
    assert q_order["total"] == sum(
        _price(item["item_id"]) * item["count"] for item in q_order["items"])

    # test only one order can be made
    res2 = make_order(uid, token, cart_id, item_items)
    assert res2.status_code == 403
    assert res2.json() == {
        "code": "ORDER_OUT_OF_LIMIT",
        "message": u"每个用户只能下一单"
    }
Example #2
0
def test_make_order():

    uid, token = next(token_gen)
    cart_id = new_cart(token)
    food_items = [next(food_gen)]

    # make order success
    res = make_order(uid, token, cart_id, food_items)
    assert res.status_code == 200
    order_id = res.json()["id"]
    assert len(order_id) > 0

    # verify query return the same order
    orders = json_get("/orders", token).json()
    assert len(orders) == 1
    q_order = orders[0]
    assert q_order["id"] == order_id
    assert q_order["items"] == food_items

    # verify order info correct
    _price = lambda i: food_store[i]["price"]
    assert q_order["total"] == sum(
        _price(item["food_id"]) * item["count"] for item in q_order["items"])

    # test only one order can be made
    res2 = make_order(uid, token, cart_id, food_items)
    assert res2.status_code == 403
    assert res2.json() == {"code": "ORDER_OUT_OF_LIMIT",
                           "message": u"每个用户只能下一单"}
def test_food_not_oversold_under_concurrent():

    TEST_FOOD_COUNT = 5
    TEST_FOOD_STOCK = 10

    # random choose foods with more than 10 stock
    test_food_ids = random.sample(
        [f for f, s in food_store.items() if s["stock"] >= TEST_FOOD_STOCK],
        TEST_FOOD_COUNT)
    for food_id in test_food_ids:
        buy_to_stock(food_id, TEST_FOOD_STOCK)
        assert food_store[food_id]["stock"] == TEST_FOOD_STOCK

    # enumerate all food items
    total_food_items = []
    for food_id in test_food_ids:
        remain_stock = food_store[food_id]["stock"]
        items = [{"food_id": food_id, "count": 1}] * remain_stock
        total_food_items.extend(items)
    assert len(total_food_items) == TEST_FOOD_COUNT * TEST_FOOD_STOCK

    # try to buy as much as twice of the stock
    test_food_items = total_food_items * 2
    random.shuffle(test_food_items)

    # prepare carts & tokens, each carts contains 2 foods
    cart_ids, tokens, items_list = [], [], []
    for food_items in zip(test_food_items[::2], test_food_items[1::2]):
        _, token = next(token_gen)
        cart_id = new_cart(token)

        for item in food_items:
            res = json_patch("/carts/%s" % cart_id, token, item)
            assert res.status_code == 204

        cart_ids.append(cart_id)
        tokens.append(token)
        items_list.append(food_items)

    def _make(cart_id, token, food_items):
        res = json_post("/orders", token, {"cart_id": cart_id})
        if res.status_code == 200:
            for food_item in food_items:
                food_store[food_item["food_id"]]["stock"] -= 1
        return res

    # make order with prepared carts, using 3 concurrent threads
    # allow sell slower (remain stock > 0)
    # best sell all and correct (remain stock == 0)
    # disallow oversold (remain stock < 0)
    with ThreadPoolExecutor(max_workers=3) as executor:
        future_results = [
            executor.submit(_make, ct, tk, fs)
            for ct, tk, fs in zip(cart_ids, tokens, items_list)]
        concurrent.futures.wait(future_results, timeout=30)

    # test not oversold
    for food_id in test_food_ids:
        print("stock %s -> %s" % (food_id, food_store[food_id]["stock"]))
        assert food_store[food_id]["stock"] >= 0
Example #4
0
def test_food_not_oversold_under_concurrent():

    TEST_FOOD_COUNT = 5
    TEST_FOOD_STOCK = 10

    # random choose foods with more than 10 stock
    test_food_ids = random.sample(
        [f for f, s in food_store.items() if s["stock"] >= TEST_FOOD_STOCK],
        TEST_FOOD_COUNT)
    for food_id in test_food_ids:
        buy_to_stock(food_id, TEST_FOOD_STOCK)
        assert food_store[food_id]["stock"] == TEST_FOOD_STOCK

    # enumerate all food items
    total_food_items = []
    for food_id in test_food_ids:
        remain_stock = food_store[food_id]["stock"]
        items = [{"food_id": food_id, "count": 1}] * remain_stock
        total_food_items.extend(items)
    assert len(total_food_items) == TEST_FOOD_COUNT * TEST_FOOD_STOCK

    # try to buy as much as twice of the stock
    test_food_items = total_food_items * 2
    random.shuffle(test_food_items)

    # prepare carts & tokens, each carts contains 2 foods
    cart_ids, tokens, items_list = [], [], []
    for food_items in zip(test_food_items[::2], test_food_items[1::2]):
        _, token = next(token_gen)
        cart_id = new_cart(token)

        for item in food_items:
            res = json_patch("/carts/%s" % cart_id, token, item)
            assert res.status_code == 204

        cart_ids.append(cart_id)
        tokens.append(token)
        items_list.append(food_items)

    def _make(cart_id, token, food_items):
        res = json_post("/orders", token, {"cart_id": cart_id})
        if res.status_code == 200:
            for food_item in food_items:
                food_store[food_item["food_id"]]["stock"] -= 1
        return res

    # make order with prepared carts, using 3 concurrent threads
    # allow sell slower (remain stock > 0)
    # best sell all and correct (remain stock == 0)
    # disallow oversold (remain stock < 0)
    with ThreadPoolExecutor(max_workers=3) as executor:
        future_results = [
            executor.submit(_make, ct, tk, fs)
            for ct, tk, fs in zip(cart_ids, tokens, items_list)]
        concurrent.futures.wait(future_results, timeout=30)

    # test not oversold
    for food_id in test_food_ids:
        # print("stock %s -> %s" % (food_id, food_store[food_id]["stock"]))
        assert food_store[food_id]["stock"] >= 0
Example #5
0
def test_cart_not_owned_error():
    _, token1 = next(token_gen)
    _, token2 = next(token_gen)
    cart_id2 = new_cart(token2)

    res = json_patch("/carts/%s" % cart_id2, token1, next(food_gen))
    assert res.status_code == 401
    assert res.json() == {"code": "NOT_AUTHORIZED_TO_ACCESS_CART",
                          "message": u"无权限访问指定的篮子"}
Example #6
0
def test_food_not_found_error():
    _, token = next(token_gen)
    cart_id = new_cart(token)

    item = {"food_id": -1, "count": 2}
    res = json_patch("/carts/%s" % cart_id, token, item)

    assert res.status_code == 404
    assert res.json() == {"code": "FOOD_NOT_FOUND", "message": u"食物不存在"}
Example #7
0
def test_make_order_cart_not_owned_error():
    uid, token1 = next(token_gen)
    cart_id1 = new_cart(token1)
    _, token2 = next(token_gen)

    res = make_order(uid, token2, cart_id1, [next(food_gen)])
    assert res.status_code == 401
    assert res.json() == {"code": "NOT_AUTHORIZED_TO_ACCESS_CART",
                          "message": u"无权限访问指定的篮子"}
Example #8
0
def test_pay_order_not_owned_error():
    uid, token1 = next(token_gen)
    cart_id1 = new_cart(token1)
    _, token2 = next(token_gen)

    res = make_order(uid, token1, cart_id1, [next(item_gen)])
    assert res.status_code == 200
    order_id1 = res.json()["order_id"]

    res = pay_order(uid, token2, order_id1)
    assert res.status_code == 401
    assert res.json() == {"code": "NOT_AUTHORIZED_TO_ACCESS_ORDER",
                          "message": u"无权限访问指定的订单"}
Example #9
0
def test_add_food():
    _, token = next(token_gen)
    cart_id = new_cart(token)

    # success add 3 food
    for i in range(3):
        res = json_patch("/carts/%s" % cart_id, token, next(food_gen))
        assert res.status_code == 204
        assert len(res.content) == 0

    # fail if try to add more
    res = json_patch("/carts/%s" % cart_id, token, next(food_gen))
    assert res.status_code == 403
    assert res.json() == {"code": "FOOD_OUT_OF_LIMIT",
                          "message": u"篮子中食物数量超过了三个"}
Example #10
0
def test_del_food():
    _, token = next(token_gen)
    cart_id = new_cart(token)
    item = next(food_gen)
    json_patch("/carts/%s" % cart_id, token, item)

    # delete existing food
    item["count"] = -1
    res = json_patch("/carts/%s" % cart_id, token, item)
    assert res.status_code == 204
    assert len(res.content) == 0

    # delete non-exist food
    res = json_patch("/carts/%s" % cart_id, token, next(food_gen))
    assert res.status_code == 204
    assert len(res.content) == 0
Example #11
0
def test_pay_order_balance_insufficient():

    uid, token = next(balance_insufficient_token_gen)
    cart_id = new_cart(token)
    item_items = [next(item_gen)]

    # make order success
    res = make_order(uid, token, cart_id, item_items)
    assert res.status_code == 200
    order_id = res.json()["order_id"]
    assert len(order_id) > 0

    res = pay_order(uid, token, order_id)
    assert res.status_code == 403
    assert res.json() == {"code": "BALANCE_INSUFFICIENT",
                          "message": u"余额不足"}
Example #12
0
def test_pay_order():

    uid, token = next(balance_ok_token_gen)
    cart_id = new_cart(token)
    item_items = [next(item_gen)]

    # make order success
    res = make_order(uid, token, cart_id, item_items)
    assert res.status_code == 200
    order_id = res.json()["order_id"]
    assert len(order_id) > 0

    res = pay_order(uid, token, order_id)
    assert res.status_code == 200

    # test only one payment can be made
    res = pay_order(uid, token, order_id)
    assert res.status_code == 403
    assert res.json() == {"code": "ORDER_PAID",
                          "message": u"订单已支付"}