Exemple #1
0
def test_check_auction_admin(password, encoded_password, admin_password,
                             result):
    if admin_password is None:
        app = create_app({})
    else:
        app = create_app({"YAMI_ADMIN_PASSWORD": admin_password})

    with app.app_context():
        assert logic.check_auction_admin(password, encoded_password) == result
Exemple #2
0
def test_get_auction_info_notfound():
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    #datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({})

    cursor_mock1 = create_cursor_mock()
    cursor_mock1.fetchone.return_value = None
    db_mock = mock.MagicMock()
    db_mock.cursor.side_effect = [cursor_mock1]

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = db_mock
        auction, bids = logic.get_auction_info(42, False)

    assert db_mock.cursor.mock_calls == [
        mock.call(pymysql.cursors.DictCursor),
    ]

    assert cursor_mock1.mock_calls == [
        mock.call.execute("SELECT * FROM t_auction WHERE auction_id = %s",
                          (42, )),
        mock.call.fetchone(),
        mock.call.close(),
    ]

    assert auction == None
    assert bids == None
Exemple #3
0
def test_cancel_auction_badpassword(initdb):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_end = datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc)

    app = create_app({
        "MYSQL_CONNECT_KWARGS": testdb.MYSQL_CONNECT_KWARGS,
    })

    with app.app_context():
        g.datetime_now = datetime_now
        auction_id, _ = logic.new_auction({
            "itemname": "foo",
            "quantity": 1,
            "username": "******",
            "datetime_end": datetime_end,
            "price_start": 456,
            "price_prompt": None,
            "price_step_min": 111,
            "location": "anyware",
            "description": "something",
        })

        g.datetime_now = datetime_now + timedelta(minutes=30)
        result = logic.cancel_auction(auction_id, "")

    assert result == logic.CancelErrorCodes.CANCEL_ERROR_BAD_PASSWORD
Exemple #4
0
def test_cancel_auction_badpassword():
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    #datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({})

    cursor_mock1 = create_cursor_mock()
    cursor_mock1.fetchone.return_value = [""]
    cursor_mock2 = create_cursor_mock()
    db_mock = mock.MagicMock()
    db_mock.cursor.side_effect = [cursor_mock1, cursor_mock2]

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = db_mock
        result = logic.cancel_auction(42, "password")

    assert result == logic.CancelErrorCodes.CANCEL_ERROR_BAD_PASSWORD

    assert db_mock.cursor.mock_calls == [
        mock.call(),
    ]

    assert cursor_mock1.mock_calls == [
        mock.call.execute(
            "SELECT password FROM t_auction_password WHERE auction_id = %s",
            (42, )),
        mock.call.fetchone(),
        mock.call.close(),
    ]
Exemple #5
0
def test_cancel_auction_seller(initdb):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_end = datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc)

    app = create_app({
        "MYSQL_CONNECT_KWARGS": testdb.MYSQL_CONNECT_KWARGS,
    })

    with app.app_context():
        g.datetime_now = datetime_now
        auction_id, password = logic.new_auction({
            "itemname": "foo",
            "quantity": 1,
            "username": "******",
            "datetime_end": datetime_end,
            "price_start": 456,
            "price_prompt": None,
            "price_step_min": 111,
            "location": "anyware",
            "description": "something",
        })

        g.datetime_now = datetime_now + timedelta(minutes=30)
        result = logic.cancel_auction(auction_id, password)
        auction, _ = logic.get_auction_info(auction_id, for_update=False)
        logic.commit()

    assert result == logic.CancelErrorCodes.CANCEL_OK
    assert auction["ended"] == 1
    assert auction["endtype"] == logic.EndType.ENDTYPE_CANCELED_BY_SELLER
    assert auction["datetime_update"] == datetime_now + timedelta(minutes=30)
Exemple #6
0
def test_cancel_auction_admin(initdb):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_end = datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc)

    app = create_app({
        "MYSQL_CONNECT_KWARGS":
        testdb.MYSQL_CONNECT_KWARGS,
        "YAMI_ADMIN_PASSWORD":
        "******"
    })

    with app.app_context():
        g.datetime_now = datetime_now
        auction_id, _ = logic.new_auction({
            "itemname": "foo",
            "quantity": 1,
            "username": "******",
            "datetime_end": datetime_end,
            "price_start": 456,
            "price_prompt": None,
            "price_step_min": 111,
            "location": "anyware",
            "description": "something",
        })

        g.datetime_now = datetime_now + timedelta(minutes=30)
        result = logic.cancel_auction(auction_id, "password")
        auction, _ = logic.get_auction_info(auction_id, for_update=False)
        logic.commit()

    assert result == logic.CancelErrorCodes.CANCEL_OK
    assert auction["ended"] == 1
    assert auction["endtype"] == logic.EndType.ENDTYPE_CANCELED_BY_ADMIN
    assert auction["datetime_update"] == datetime_now + timedelta(minutes=30)
Exemple #7
0
def test_bid_auction_manytimes(initdb):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_end = datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc)
    datetime_bid = datetime(2000, 6, 7, 8, 9, 10, tzinfo=timezone.utc)

    app = create_app({
        "MYSQL_CONNECT_KWARGS": testdb.MYSQL_CONNECT_KWARGS,
        "YAMI_PRICE_STEP_MIN": 111,
        "YAMI_PRICE_STEP_FROM_CURRENT_PRICE": True,
        "YAMI_PRICE_STEP_RULE": {
            1: 1,
        },
        "YAMI_AUTO_EXTENSION": 0,
    })

    with app.app_context():
        g.datetime_now = datetime_now
        auction_id, _ = logic.new_auction({
            "itemname": "foo",
            "quantity": 2,
            "username": "******",
            "datetime_end": datetime_end,
            "price_start": 456,
            "price_prompt": None,
            "price_step_min": 111,
            "location": "anyware",
            "description": "something",
        })
        logic.commit()

    bid_results = []
    with app.app_context():
        for i in range(5):
            g.datetime_now = datetime_bid + timedelta(days=i + 1)
            bid_results.append(
                logic.bid_auction({
                    "auction_id": auction_id,
                    "username": "******" + str(i),
                    "price": 1000 * (i + 1),
                }))
        auction, bids = logic.get_auction_info(auction_id, for_update=False)
        auctions, _ = logic.get_auction_list(1, 0, False)
        logic.commit()

    for i in range(5):
        assert bid_results[i] == logic.BidErrorCodes.BID_OK

    assert not auction["ended"]
    assert auction["datetime_update"] == datetime_bid + timedelta(days=5)
    assert auction["price_current_low"] == 4000
    assert auctions[0]["price_current_low"] == 4000
    for i in range(5):
        assert bids[i] == {
            "bid_id": 5 - i,
            "auction_id": auction_id,
            "username": "******" + str(4 - i),
            "price": 1000 * (5 - i),
            "datetime_bid": datetime_bid + timedelta(days=5 - i),
        }
Exemple #8
0
def test_new_auction(monkeypatch):
    app = create_app({})
    auction = {
        "itemname": "foo",
        "quantity": 123,
        "username": "******",
        "datetime_end": datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc),
        "price_start": 456,
        "price_prompt": 789,
        "price_step_min": 111,
        "location": "anyware",
        "description": "something",
    }
    cursor_mock = create_cursor_mock()
    cursor_mock.fetchone.return_value = (42, )
    db_mock = mock.MagicMock()
    db_mock.cursor.side_effect = [cursor_mock]

    secret_token_hex_mock = mock.MagicMock()
    secret_token_hex_mock.return_value = "0123456789abcdef"
    monkeypatch.setattr(secrets, "token_hex", secret_token_hex_mock)

    secret_token_urlsafe_mock = mock.MagicMock()
    secret_token_urlsafe_mock.return_value = "AZaz09_-"
    monkeypatch.setattr(secrets, "token_urlsafe", secret_token_urlsafe_mock)

    with app.app_context():
        g.datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
        g.db = db_mock
        auction_id, password = logic.new_auction(auction)

    assert db_mock.cursor.mock_calls == [
        mock.call(),
    ]

    assert cursor_mock.mock_calls == [
        mock.call.execute(
            "INSERT INTO t_auction (type, itemname, quantity, username, datetime_start, datetime_end, datetime_update, price_start, price_prompt, price_step_min, location, description) VALUES (1, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
            ("foo", 123, "bar",
             datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc),
             datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc),
             datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc), 456, 789, 111,
             "anyware", "something")),
        mock.call.execute("SELECT LAST_INSERT_ID() FROM t_auction"),
        mock.call.fetchone(),
        mock.call.execute(
            "INSERT INTO t_auction_password (auction_id, password) VALUES (%s, %s)",
            (42,
             "pbkdf2_sha256$36000$AZaz09_-$A/eop0d997YvWCSWHt9JxKihD3A0EZiXdjXdL9VRvwU="
             )),
        mock.call.close(),
    ]
    assert cursor_mock.execute.mock_calls[0][1][1][3].tzinfo == timezone.utc
    assert cursor_mock.execute.mock_calls[0][1][1][4].tzinfo == timezone.utc
    assert cursor_mock.execute.mock_calls[0][1][1][5].tzinfo == timezone.utc

    assert auction_id == 42
    assert password == "0123456789abcdef"
Exemple #9
0
def test_bid_auction_error(initdb):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_end = datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc)

    app = create_app({
        "MYSQL_CONNECT_KWARGS": testdb.MYSQL_CONNECT_KWARGS,
    })

    with app.app_context():
        g.datetime_now = datetime_now
        bid_result = logic.bid_auction({
            "auction_id": 1,
            "username": "******",
            "price": 100,
        })
        logic.commit()

    assert bid_result == logic.BidErrorCodes.BID_ERROR_NOT_FOUND

    with app.app_context():
        g.datetime_now = datetime_now
        auction_id, _ = logic.new_auction({
            "itemname": "foo",
            "quantity": 123,
            "username": "******",
            "datetime_end": datetime_end,
            "price_start": 456,
            "price_prompt": 789,
            "price_step_min": 111,
            "location": "anyware",
            "description": "something",
        })
        logic.commit()

    with app.app_context():
        g.datetime_now = datetime_now
        bid_result = logic.bid_auction({
            "auction_id": auction_id,
            "username": "******",
            "price": 100,
        })
        logic.commit()

    assert bid_result == logic.BidErrorCodes.BID_ERROR_ANOTHER_ONE_BIDDED_FIRST

    with app.app_context():
        g.datetime_now = datetime_end
        bid_result = logic.bid_auction({
            "auction_id": auction_id,
            "username": "******",
            "price": 1000,
        })
        logic.commit()

    assert bid_result == logic.BidErrorCodes.BID_ERROR_ALREADY_ENDED
Exemple #10
0
def test_cancel_auction_ok(isadmin, monkeypatch):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    #datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({
        "YAMI_ADMIN_PASSWORD":
        "******"
        if isadmin else ""
    })

    get_auction_info_mock = mock.MagicMock()
    get_auction_info_mock.return_value = ({}, [])
    monkeypatch.setattr(
        logic, "get_auction_info",
        lambda auction_id, for_update: get_auction_info_mock(
            auction_id, for_update))

    cursor_mock1 = create_cursor_mock()
    cursor_mock1.fetchone.return_value = [
        "pbkdf2_sha256$100000$salt$A5Si7eMyyaE+uC6bJGMWBMMd+Xi04vD70sVJlE+deaU="
        if not isadmin else ""
    ]
    cursor_mock2 = create_cursor_mock()
    db_mock = mock.MagicMock()
    db_mock.cursor.side_effect = [cursor_mock1, cursor_mock2]

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = db_mock
        result = logic.cancel_auction(42, "password")

    assert result == logic.CancelErrorCodes.CANCEL_OK

    assert db_mock.cursor.mock_calls == [
        mock.call(),
        mock.call(),
    ]

    assert cursor_mock1.mock_calls == [
        mock.call.execute(
            "SELECT password FROM t_auction_password WHERE auction_id = %s",
            (42, )),
        mock.call.fetchone(),
        mock.call.close(),
    ]

    assert cursor_mock2.mock_calls == [
        mock.call.execute(
            "UPDATE t_auction SET ended = 1, endtype = %s, datetime_update = %s WHERE auction_id = %s",
            (logic.EndType.ENDTYPE_CANCELED_BY_ADMIN if isadmin else
             logic.EndType.ENDTYPE_CANCELED_BY_SELLER, datetime_now, 42)),
        mock.call.close(),
    ]
Exemple #11
0
def test_bid_auction_another_one_bidded_first(monkeypatch):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    #datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({})
    newbid = {
        "auction_id": 42,
        "price": 100,
    }

    get_auction_info_mock = mock.MagicMock()
    get_auction_info_mock.return_value = ({
        "auction_id":
        42,
        "quantity":
        3,
        "price_start":
        10,
        "price_prompt":
        None,
        "price_step_min":
        100,
        "ended":
        False,
        "datetime_end":
        datetime_now - timedelta(days=1),
        "price_bid_min":
        200,
    }, [{
        "bid_id": 3,
        "price": 100,
    }, {
        "bid_id": 2,
        "price": 50,
    }, {
        "bid_id": 1,
        "price": 10,
    }])
    monkeypatch.setattr(logic, "get_auction_info", get_auction_info_mock)

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = None
        result = logic.bid_auction(newbid)

    get_auction_info_mock.mock_calls == [
        mock.call(42, for_update=True),
    ]

    assert result == logic.BidErrorCodes.BID_ERROR_ANOTHER_ONE_BIDDED_FIRST
Exemple #12
0
def test_cancel_auction_notfound(initdb):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_end = datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc)

    app = create_app({
        "MYSQL_CONNECT_KWARGS": testdb.MYSQL_CONNECT_KWARGS,
    })

    with app.app_context():
        g.datetime_now = datetime_now
        result = logic.cancel_auction(42, "")
        logic.commit()

    assert result == logic.CancelErrorCodes.CANCEL_ERROR_NOT_FOUND
Exemple #13
0
def test_get_auction_info_notfound(initdb):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)

    app = create_app({
        "MYSQL_CONNECT_KWARGS": testdb.MYSQL_CONNECT_KWARGS,
    })

    with app.app_context():
        g.datetime_now = datetime_now
        auction, bids = logic.get_auction_info(42, for_update=False)
        auctions, num_auctions = logic.get_auction_list(10, 0, False)

    assert auction is None
    assert bids is None
    assert len(auctions) == 0
    assert num_auctions == 0
def test_calc_price_step_min_when_zero_price(config_price_step_min, auction_price_step_min, result):
	app = create_app({
		"YAMI_PRICE_STEP_FROM_CURRENT_PRICE": False,
		"YAMI_PRICE_STEP_MIN": config_price_step_min,
		"YAMI_PRICE_STEP_RULE": {
			1: "0.2",
			2: "0.4",
			4: "1",
		},
	})
	auction = {
		"price_step_min": auction_price_step_min,
		"price_start": 0,
		"price_current_low": 0,
	}
	with app.app_context():
		assert logic.calc_price_step_min(auction) == result
def test_set_price_bid_min(price_start, price_prompt, price_current_low, result):
	app = create_app({
		"YAMI_PRICE_STEP_FROM_CURRENT_PRICE": True,
		"YAMI_PRICE_STEP_MIN": 1000,
		"YAMI_PRICE_STEP_RULE": {
			1: "0.2",
			2: "0.4",
			4: "1",
		},
	})
	auction = {
		"price_step_min": 1000,
		"price_start": price_start,
		"price_prompt": price_prompt,
		"price_current_low": price_current_low,
	}
	with app.app_context():
		logic.set_price_bid_min(auction)
		assert auction["price_bid_min"] == result
def test_calc_price_step_min_from_current_price(price_current_low, result):
	app = create_app({
		"YAMI_PRICE_STEP_FROM_CURRENT_PRICE": True,
		"YAMI_PRICE_STEP_MIN": 1000,
		"YAMI_PRICE_STEP_RULE": {
			1: "0.2",
			2: "0.4",
			4: "1",
		},
	})
	auction = {
		"price_step_min": 1000,
		"price_current_low": price_current_low,
	}
	with app.app_context():
		auction["price_start"] = 0
		assert logic.calc_price_step_min(auction) == result
		auction["price_start"] = 100000
		assert logic.calc_price_step_min(auction) == result
Exemple #17
0
def test_bid_auction_extension(quantity, prompt, extended, initdb):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_end = datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc)
    yami_auto_extension = 3600

    app = create_app({
        "MYSQL_CONNECT_KWARGS": testdb.MYSQL_CONNECT_KWARGS,
        "YAMI_PRICE_STEP_MIN": 111,
        "YAMI_PRICE_STEP_FROM_CURRENT_PRICE": True,
        "YAMI_PRICE_STEP_RULE": {
            1: 1,
        },
        "YAMI_AUTO_EXTENSION": yami_auto_extension,
    })

    with app.app_context():
        g.datetime_now = datetime_now
        auction_id, _ = logic.new_auction({
            "itemname": "foo",
            "quantity": quantity,
            "username": "******",
            "datetime_end": datetime_end,
            "price_start": 456,
            "price_prompt": 1000,
            "price_step_min": 111,
            "location": "anyware",
            "description": "something",
        })
        logic.commit()

    with app.app_context():
        g.datetime_now = datetime_end - timedelta(minutes=30)
        logic.bid_auction({
            "auction_id": auction_id,
            "username": "******",
            "price": 1000 if prompt else 500,
        })
        auction, _ = logic.get_auction_info(auction_id, for_update=False)
        logic.commit()

    assert auction["datetime_end"] == datetime_end + (
        -timedelta(minutes=30) +
        timedelta(seconds=yami_auto_extension) if extended else timedelta())
Exemple #18
0
def test_bid_auction_notfound(monkeypatch):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    #datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({})
    newbid = {
        "auction_id": 42,
    }

    get_auction_info_mock = mock.MagicMock()
    get_auction_info_mock.return_value = (None, None)
    monkeypatch.setattr(logic, "get_auction_info", get_auction_info_mock)

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = None
        result = logic.bid_auction(newbid)

    get_auction_info_mock.mock_calls == [
        mock.call(42, for_update=True),
    ]

    assert result == logic.BidErrorCodes.BID_ERROR_NOT_FOUND
Exemple #19
0
#!/usr/bin/python3

# 時間切れによる終了処理を行う

from flask import g
from yami import create_app, logic
from datetime import datetime, timezone

app = create_app()

with app.app_context():
    g.datetime_now = datetime.now(timezone.utc)
    logic.check_expiration()
Exemple #20
0
def test_get_auction_list_ended():
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({
        "YAMI_PRICE_STEP_FROM_CURRENT_PRICE": False,
        "YAMI_PRICE_STEP_MIN": 100,
        "YAMI_PRICE_STEP_RULE": {
            1: 1
        }
    })

    cursor_mock1 = create_cursor_mock()
    cursor_mock1.fetchone.return_value = (123, )
    cursor_mock2 = create_cursor_mock()
    cursor_mock2.fetchall.return_value = [
        {
            # ended = true, datetime_end > now
            "auction_id": 2,
            "quantity": 1,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 1,
            "datetime_end": datetime_now_naive + timedelta(days=1),
            "price_current_high": None,
            "num_bids": None,
        },
        {
            # ended = false, datetime_end = now
            "auction_id": 3,
            "quantity": 1,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 0,
            "datetime_end": datetime_now_naive,
            "price_current_high": None,
            "num_bids": None,
        },
        {
            # ended = false, datetime_end < now
            "auction_id": 1,
            "quantity": 1,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 0,
            "datetime_end": datetime_now_naive - timedelta(days=1),
            "price_current_high": None,
            "num_bids": None,
        }
    ]
    db_mock = mock.MagicMock()
    db_mock.cursor.side_effect = [cursor_mock1, cursor_mock2]

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = db_mock
        auctions, num_auctions = logic.get_auction_list(10, 20, False)

    assert db_mock.cursor.mock_calls == [
        mock.call(),
        mock.call(pymysql.cursors.DictCursor),
    ]

    assert cursor_mock1.mock_calls == [
        mock.call.execute(
            "SELECT COUNT(auction_id) FROM t_auction WHERE (ended = false AND datetime_end > %s)",
            (datetime_now, )),
        mock.call.fetchone(),
        mock.call.close(),
    ]

    assert cursor_mock2.mock_calls == [
        mock.call.execute(
            "SELECT * FROM t_auction LEFT JOIN (SELECT auction_id, MAX(price) as price_current_high, COUNT(price) as num_bids FROM t_bid GROUP BY auction_id) AS maxbid USING(auction_id) WHERE (ended = false AND datetime_end > %s) ORDER BY datetime_end ASC LIMIT %s OFFSET %s",
            (datetime_now, 10, 20)),
        mock.call.fetchall(),
        mock.call.close(),
    ]

    assert num_auctions == 123
    assert auctions == [{
        "auction_id": 2,
        "quantity": 1,
        "price_start": 10,
        "price_prompt": None,
        "price_step_min": 100,
        "ended": True,
        "datetime_end": datetime_now + timedelta(days=1),
        "price_current_high": None,
        "price_current_low": None,
        "price_bid_min": 10,
        "num_bids": 0,
    }, {
        "auction_id": 3,
        "quantity": 1,
        "price_start": 10,
        "price_prompt": None,
        "price_step_min": 100,
        "ended": True,
        "datetime_end": datetime_now,
        "price_current_high": None,
        "price_current_low": None,
        "price_bid_min": 10,
        "num_bids": 0,
    }, {
        "auction_id": 1,
        "quantity": 1,
        "price_start": 10,
        "price_prompt": None,
        "price_step_min": 100,
        "ended": True,
        "datetime_end": datetime_now - timedelta(days=1),
        "price_current_high": None,
        "price_current_low": None,
        "price_bid_min": 10,
        "num_bids": 0,
    }]
    for auction in auctions:
        assert auction["datetime_end"].tzinfo == timezone.utc
Exemple #21
0
def test_new_auction(initdb, monkeypatch):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_end = datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc)

    secret_token_hex_mock = mock.MagicMock()
    secret_token_hex_mock.return_value = "0123456789abcdef"
    monkeypatch.setattr(secrets, "token_hex", secret_token_hex_mock)

    app = create_app({
        "MYSQL_CONNECT_KWARGS": testdb.MYSQL_CONNECT_KWARGS,
    })

    with app.app_context():
        g.datetime_now = datetime_now
        auction_id, password = logic.new_auction({
            "itemname": "foo",
            "quantity": 123,
            "username": "******",
            "datetime_end": datetime_end,
            "price_start": 456,
            "price_prompt": 789,
            "price_step_min": 111,
            "location": "anyware",
            "description": "something",
        })
        auction, bids = logic.get_auction_info(auction_id, for_update=False)
        held_auctions, num_held_auctions = logic.get_auction_list(10, 0, False)
        out_of_page_held_auctions, num_held_auctions_2 = logic.get_auction_list(
            10, 10, False)
        ended_auctions, num_ended_auctions = logic.get_auction_list(
            10, 0, True)
        logic.commit()

    expected_auction = {
        "auction_id": 1,
        "type": 1,
        "itemname": "foo",
        "quantity": 123,
        "username": "******",
        "datetime_start": datetime_now,
        "datetime_end": datetime_end,
        "datetime_update": datetime_now,
        "price_start": 456,
        "price_prompt": 789,
        "price_step_min": 111,
        "location": "anyware",
        "description": "something",
        "ended": False,
        "endtype": 0,
        "price_bid_min": 456,
        "price_current_high": None,
        "price_current_low": None,
    }
    expected_auction_in_list = expected_auction.copy()
    expected_auction_in_list["num_bids"] = 0

    assert auction_id == 1
    assert password == "0123456789abcdef"

    assert auction == expected_auction
    assert len(bids) == 0

    assert held_auctions == [expected_auction_in_list]
    assert num_held_auctions == 1
    assert len(out_of_page_held_auctions) == 0
    assert num_held_auctions_2 == 1
    assert len(ended_auctions) == 0
    assert num_ended_auctions == 0

    with app.app_context():
        g.datetime_now = datetime_end
        auction, bids = logic.get_auction_info(auction_id, for_update=False)
        held_auctions, num_held_auctions = logic.get_auction_list(10, 0, False)
        ended_auctions, num_ended_auctions = logic.get_auction_list(
            10, 0, True)
        logic.commit()

    expected_auction["ended"] = True
    expected_auction_in_list["ended"] = True

    assert auction == expected_auction
    assert len(bids) == 0

    assert len(held_auctions) == 0
    assert num_held_auctions == 0
    assert ended_auctions == [expected_auction_in_list]
    assert num_ended_auctions == 1
Exemple #22
0
def test_get_auction_info_query(for_update):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({
        "YAMI_PRICE_STEP_FROM_CURRENT_PRICE": False,
        "YAMI_PRICE_STEP_MIN": 100,
        "YAMI_PRICE_STEP_RULE": {
            1: 1
        }
    })

    cursor_mock1 = create_cursor_mock()
    cursor_mock1.fetchone.return_value = {
        "auction_id": 42,
        "quantity": 1,
        "price_start": 10,
        "price_prompt": None,
        "price_step_min": 100,
        "ended": 0,
        "datetime_end": datetime_now_naive + timedelta(days=1),
    }
    cursor_mock2 = create_cursor_mock()
    cursor_mock2.fetchall.return_value = [{
        "bid_id": 3,
        "price": 100,
    }, {
        "bid_id": 1,
        "price": 50,
    }]
    db_mock = mock.MagicMock()
    db_mock.cursor.side_effect = [cursor_mock1, cursor_mock2]

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = db_mock
        auction, bids = logic.get_auction_info(42, for_update)

    assert db_mock.cursor.mock_calls == [
        mock.call(pymysql.cursors.DictCursor),
        mock.call(pymysql.cursors.DictCursor),
    ]

    if for_update:
        auction_select_decoration = " FOR UPDATE"
    else:
        auction_select_decoration = ""
    assert cursor_mock1.mock_calls == [
        mock.call.execute(
            "SELECT * FROM t_auction WHERE auction_id = %s" +
            auction_select_decoration, (42, )),
        mock.call.fetchone(),
        mock.call.close(),
    ]

    if for_update:
        bid_select_decoration = " LIMIT %s"
        bid_select_parameters = (42, 1)
    else:
        bid_select_decoration = ""
        bid_select_parameters = (42, )
    assert cursor_mock2.mock_calls == [
        mock.call.execute(
            "SELECT * FROM t_bid WHERE auction_id = %s ORDER BY price DESC, datetime_bid ASC"
            + bid_select_decoration, bid_select_parameters),
        mock.call.fetchall(),
        mock.call.close(),
    ]

    assert auction == {
        "auction_id": 42,
        "quantity": 1,
        "price_start": 10,
        "price_prompt": None,
        "price_step_min": 100,
        "ended": False,
        "datetime_end": datetime_now + timedelta(days=1),
        "price_current_high": 100,
        "price_current_low": 100,
        "price_bid_min": 200,
    }
    assert bids == [{
        "bid_id": 3,
        "price": 100,
    }, {
        "bid_id": 1,
        "price": 50,
    }]
Exemple #23
0
def test_bid_auction_prompt(initdb):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_end = datetime(2000, 12, 11, 10, 9, 8, tzinfo=timezone.utc)
    datetime_bid = datetime(2000, 6, 7, 8, 9, 10, tzinfo=timezone.utc)

    app = create_app({
        "MYSQL_CONNECT_KWARGS": testdb.MYSQL_CONNECT_KWARGS,
        "YAMI_PRICE_STEP_MIN": 111,
        "YAMI_PRICE_STEP_FROM_CURRENT_PRICE": True,
        "YAMI_PRICE_STEP_RULE": {
            1: 1,
        }
    })

    with app.app_context():
        g.datetime_now = datetime_now
        auction_id, _ = logic.new_auction({
            "itemname": "foo",
            "quantity": 1,
            "username": "******",
            "datetime_end": datetime_end,
            "price_start": 456,
            "price_prompt": 789,
            "price_step_min": 111,
            "location": "anyware",
            "description": "something",
        })
        logic.commit()

    with app.app_context():
        g.datetime_now = datetime_bid
        bid_result = logic.bid_auction({
            "auction_id": auction_id,
            "username": "******",
            "price": 789,
        })
        auction, bids = logic.get_auction_info(auction_id, for_update=False)
        logic.commit()

    assert bid_result == logic.BidErrorCodes.BID_OK

    assert auction["ended"]
    assert auction["datetime_update"] == datetime_bid
    assert bids == [{
        "bid_id": 1,
        "auction_id": auction_id,
        "username": "******",
        "price": 789,
        "datetime_bid": datetime_bid,
    }]

    with app.app_context():
        g.datetime_now = datetime_bid
        bid_result = logic.bid_auction({
            "auction_id": auction_id,
            "username": "******",
            "price": 1000,
        })
        logic.commit()

    assert bid_result == logic.BidErrorCodes.BID_ERROR_ALREADY_ENDED
Exemple #24
0
def test_get_auction_info_price(num_bids):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({
        "YAMI_PRICE_STEP_FROM_CURRENT_PRICE": False,
        "YAMI_PRICE_STEP_MIN": 100,
        "YAMI_PRICE_STEP_RULE": {
            1: 1
        }
    })

    cursor_mock1 = create_cursor_mock()
    cursor_mock1.fetchone.return_value = {
        "auction_id": 42,
        "quantity": 3,
        "price_start": 10,
        "price_prompt": None,
        "price_step_min": 100,
        "ended": 0,
        "datetime_end": datetime_now_naive + timedelta(days=1),
    }
    cursor_mock2 = create_cursor_mock()
    cursor_mock2.fetchall.return_value = [{
        "bid_id":
        i,
        "price":
        i * 100,
        "datetime_bid":
        datetime_now_naive - timedelta(hours=num_bids - i + 1),
    } for i in range(num_bids, 0, -1)]
    db_mock = mock.MagicMock()
    db_mock.cursor.side_effect = [cursor_mock1, cursor_mock2]

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = db_mock
        auction, bids = logic.get_auction_info(42, False)

    assert db_mock.cursor.mock_calls == [
        mock.call(pymysql.cursors.DictCursor),
        mock.call(pymysql.cursors.DictCursor),
    ]

    assert cursor_mock1.mock_calls == [
        mock.call.execute("SELECT * FROM t_auction WHERE auction_id = %s",
                          (42, )),
        mock.call.fetchone(),
        mock.call.close(),
    ]

    assert cursor_mock2.mock_calls == [
        mock.call.execute(
            "SELECT * FROM t_bid WHERE auction_id = %s ORDER BY price DESC, datetime_bid ASC",
            (42, )),
        mock.call.fetchall(),
        mock.call.close(),
    ]

    assert auction == {
        "auction_id": 42,
        "quantity": 3,
        "price_start": 10,
        "price_prompt": None,
        "price_step_min": 100,
        "ended": False,
        "datetime_end": datetime_now + timedelta(days=1),
        "price_current_high": None if num_bids == 0 else num_bids * 100,
        "price_current_low": None if num_bids < 3 else (num_bids - 2) * 100,
        "price_bid_min": 10 if num_bids < 3 else (num_bids - 1) * 100,
    }
    assert bids == [{
        "bid_id":
        i,
        "price":
        i * 100,
        "datetime_bid":
        datetime_now - timedelta(hours=num_bids - i + 1),
    } for i in range(num_bids, 0, -1)]
    for bid in bids:
        assert bid["datetime_bid"].tzinfo == timezone.utc
Exemple #25
0
def test_check_expiration(monkeypatch):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    #datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({})
    auctions = [{
        "auction_id": 1,
        "quantity": 2,
        "price_prompt": None,
        "ended": 0,
    }, {
        "auction_id": 2,
        "quantity": 2,
        "price_prompt": 100,
        "ended": 0,
    }]

    end_auction_mock = mock.MagicMock()
    monkeypatch.setattr(logic, "end_auction", end_auction_mock)

    cursor_mock1 = create_cursor_mock()
    cursor_mock1.fetchall.return_value = auctions
    cursor_mock2 = create_cursor_mock()
    cursor_mock2.fetchall.return_value = [{
        "bid_id": 1,
        "price": 100
    }, {
        "bid_id": 2,
        "price": 80
    }]
    cursor_mock3 = create_cursor_mock()
    cursor_mock4 = create_cursor_mock()
    cursor_mock4.fetchall.return_value = [{
        "bid_id": 1,
        "price": 100
    }, {
        "bid_id": 2,
        "price": 80
    }]
    cursor_mock5 = create_cursor_mock()
    db_mock = mock.MagicMock()
    db_mock.cursor.side_effect = [
        cursor_mock1, cursor_mock2, cursor_mock3, cursor_mock4, cursor_mock5
    ]

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = db_mock
        logic.check_expiration()

    assert db_mock.cursor.mock_calls == [
        mock.call(pymysql.cursors.DictCursor),
        mock.call(pymysql.cursors.DictCursor),
        mock.call(),
        mock.call(pymysql.cursors.DictCursor),
        mock.call(),
    ]

    assert cursor_mock1.mock_calls == [
        mock.call.execute(
            "SELECT * FROM t_auction WHERE ended = false AND datetime_end <= %s FOR UPDATE",
            (datetime_now, )),
        mock.call.fetchall(),
        mock.call.close(),
    ]

    assert cursor_mock2.mock_calls == [
        mock.call.execute(
            "SELECT * FROM t_bid WHERE auction_id = %s ORDER BY price DESC, datetime_bid ASC LIMIT %s",
            (1, 2)),
        mock.call.fetchall(),
        mock.call.close(),
    ]

    assert cursor_mock3.mock_calls == [
        mock.call.execute(
            "UPDATE t_auction SET datetime_update = datetime_end WHERE auction_id = %s",
            (1, )),
        mock.call.close(),
    ]

    assert cursor_mock4.mock_calls == [
        mock.call.execute(
            "SELECT * FROM t_bid WHERE auction_id = %s ORDER BY price DESC, datetime_bid ASC LIMIT %s",
            (2, 2)),
        mock.call.fetchall(),
        mock.call.close(),
    ]

    assert cursor_mock5.mock_calls == [
        mock.call.execute(
            "UPDATE t_auction SET datetime_update = datetime_end WHERE auction_id = %s",
            (2, )),
        mock.call.close(),
    ]

    assert end_auction_mock.mock_calls == [
        mock.call({
            "auction_id": 1,
            "quantity": 2,
            "price_prompt": None,
            "ended": True,
        }),
        mock.call({
            "auction_id": 2,
            "quantity": 2,
            "price_prompt": 100,
            "ended": True,
        }),
    ]
Exemple #26
0
def test_bid_auction_ok(quantity, enddelta, price_prompt, price_bidded, ended,
                        extend, monkeypatch):
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)
    #datetime_now_naive = datetime_now.replace(tzinfo=None)

    app = create_app({
        "YAMI_AUTO_EXTENSION": 300,
    })
    newbid = {
        "auction_id": 42,
        "price": 250,
        "username": "******",
    }

    get_auction_info_mock = mock.MagicMock()
    get_auction_info_mock.return_value = ({
        "auction_id":
        42,
        "quantity":
        quantity,
        "price_start":
        10,
        "price_prompt":
        price_prompt,
        "price_step_min":
        100,
        "ended":
        False,
        "datetime_end":
        datetime_now + timedelta(seconds=enddelta),
        "price_bid_min":
        200,
    }, [{
        "bid_id": 3,
        "price": 100,
    }, {
        "bid_id": 2,
        "price": 50,
    }, {
        "bid_id": 1,
        "price": 10,
    }])
    monkeypatch.setattr(logic, "get_auction_info", get_auction_info_mock)

    end_auction_mock = mock.MagicMock()
    monkeypatch.setattr(logic, "end_auction", end_auction_mock)

    cursor_mock1 = create_cursor_mock()
    cursor_mock1.fetchone.return_value = (4, )
    cursor_mock2 = create_cursor_mock()
    cursor_mock3 = create_cursor_mock()
    db_mock = mock.MagicMock()
    db_side_effect = [cursor_mock1, cursor_mock3]
    if extend:
        db_side_effect.insert(1, cursor_mock2)
    db_mock.cursor.side_effect = db_side_effect

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = db_mock
        result = logic.bid_auction(newbid)

    assert get_auction_info_mock.mock_calls == [
        mock.call(42, for_update=True),
    ]

    assert end_auction_mock.mock_calls == ([
        mock.call({
            "auction_id": 42,
            "quantity": quantity,
            "price_start": 10,
            "price_prompt": price_prompt,
            "price_step_min": 100,
            "ended": True,
            "datetime_end": datetime_now + timedelta(seconds=enddelta),
            "price_bid_min": 200,
        })
    ] if ended else [])

    assert db_mock.cursor.mock_calls == ([
        mock.call(),
        mock.call(),
        mock.call(),
    ] if extend else [
        mock.call(),
        mock.call(),
    ])

    assert cursor_mock1.mock_calls == [
        mock.call.execute(
            "INSERT INTO t_bid (auction_id, username, price, datetime_bid) VALUES (%s, %s, %s, %s)",
            (42, "bidder", price_bidded, datetime_now)),
        mock.call.execute("SELECT LAST_INSERT_ID() FROM t_bid"),
        mock.call.fetchone(),
        mock.call.close(),
    ]

    assert cursor_mock2.mock_calls == ([
        mock.call.execute(
            "UPDATE t_auction SET datetime_end = %s WHERE auction_id = %s",
            (datetime_now + timedelta(seconds=300), 42)),
        mock.call.close(),
    ] if extend else [])

    assert cursor_mock3.mock_calls == [
        mock.call.execute(
            "UPDATE t_auction SET datetime_update = %s WHERE auction_id = %s",
            (datetime_now, 42)),
        mock.call.close(),
    ]

    assert result == logic.BidErrorCodes.BID_OK
    assert newbid["bid_id"] == 4
    assert newbid["price"] == price_bidded
    assert newbid["datetime_bid"] == datetime_now
Exemple #27
0
def test_get_auction_list_held():
    datetime_now = datetime(2000, 1, 2, 3, 4, 5, tzinfo=timezone.utc)

    app = create_app({
        "YAMI_PRICE_STEP_FROM_CURRENT_PRICE": False,
        "YAMI_PRICE_STEP_MIN": 100,
        "YAMI_PRICE_STEP_RULE": {
            1: 1
        }
    })

    cursor_mock1 = create_cursor_mock()
    cursor_mock1.fetchone.return_value = (123, )
    cursor_mock2 = create_cursor_mock()
    cursor_mock2.fetchall.return_value = [
        {
            # no bids
            "auction_id": 5,
            "quantity": 1,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 0,
            "datetime_end": datetime(2000, 2, 3),
            "price_current_high": None,
            "num_bids": None,
        },
        {
            # no bids
            "auction_id": 3,
            "quantity": 3,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 0,
            "datetime_end": datetime(2000, 4, 5),
            "price_current_high": None,
            "num_bids": None,
        },
        {
            # 0 < num_bids < quantity
            "auction_id": 6,
            "quantity": 3,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 0,
            "datetime_end": datetime(2000, 6, 7),
            "price_current_high": 345,
            "num_bids": 2,
        },
        {
            # num_bids == quantity
            "auction_id": 1,
            "quantity": 1,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 0,
            "datetime_end": datetime(2000, 8, 9),
            "price_current_high": 456,
            "num_bids": 1,
        },
        {
            # num_bids == quantity
            "auction_id": 2,
            "quantity": 3,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 0,
            "datetime_end": datetime(2000, 9, 1),
            "price_current_high": 567,
            "num_bids": 3,
        },
        {
            # num_bids > quantity
            "auction_id": 4,
            "quantity": 1,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 0,
            "datetime_end": datetime(2000, 10, 2),
            "price_current_high": 678,
            "num_bids": 5,
        },
        {
            # num_bids > quantity
            "auction_id": 7,
            "quantity": 5,
            "price_start": 10,
            "price_prompt": None,
            "price_step_min": 100,
            "ended": 0,
            "datetime_end": datetime(2000, 11, 3),
            "price_current_high": 789,
            "num_bids": 7,
        }
    ]
    cursor_mock3 = create_cursor_mock()
    cursor_mock3.fetchone.return_value = (123, )
    cursor_mock4 = create_cursor_mock()
    cursor_mock4.fetchone.return_value = (234, )
    db_mock = mock.MagicMock()
    db_mock.cursor.side_effect = [
        cursor_mock1, cursor_mock2, cursor_mock3, cursor_mock4
    ]

    with app.app_context():
        g.datetime_now = datetime_now
        g.db = db_mock
        auctions, num_auctions = logic.get_auction_list(10, 20, False)

    assert db_mock.cursor.mock_calls == [
        mock.call(),
        mock.call(pymysql.cursors.DictCursor),
        mock.call(),
        mock.call(),
    ]

    assert cursor_mock1.mock_calls == [
        mock.call.execute(
            "SELECT COUNT(auction_id) FROM t_auction WHERE (ended = false AND datetime_end > %s)",
            (datetime_now, )),
        mock.call.fetchone(),
        mock.call.close(),
    ]

    assert cursor_mock2.mock_calls == [
        mock.call.execute(
            "SELECT * FROM t_auction LEFT JOIN (SELECT auction_id, MAX(price) as price_current_high, COUNT(price) as num_bids FROM t_bid GROUP BY auction_id) AS maxbid USING(auction_id) WHERE (ended = false AND datetime_end > %s) ORDER BY datetime_end ASC LIMIT %s OFFSET %s",
            (datetime_now, 10, 20)),
        mock.call.fetchall(),
        mock.call.close(),
    ]

    assert cursor_mock3.mock_calls == [
        mock.call.execute(
            "SELECT price FROM t_bid WHERE auction_id = %s ORDER BY price DESC LIMIT 1 OFFSET %s",
            (2, 2)),
        mock.call.fetchone(),
        mock.call.close(),
    ]

    assert cursor_mock4.mock_calls == [
        mock.call.execute(
            "SELECT price FROM t_bid WHERE auction_id = %s ORDER BY price DESC LIMIT 1 OFFSET %s",
            (7, 4)),
        mock.call.fetchone(),
        mock.call.close(),
    ]

    assert num_auctions == 123
    assert auctions == [{
        "auction_id":
        5,
        "quantity":
        1,
        "price_start":
        10,
        "price_prompt":
        None,
        "price_step_min":
        100,
        "ended":
        False,
        "datetime_end":
        datetime(2000, 2, 3, tzinfo=timezone.utc),
        "price_current_high":
        None,
        "price_current_low":
        None,
        "price_bid_min":
        10,
        "num_bids":
        0,
    }, {
        "auction_id":
        3,
        "quantity":
        3,
        "price_start":
        10,
        "price_prompt":
        None,
        "price_step_min":
        100,
        "ended":
        False,
        "datetime_end":
        datetime(2000, 4, 5, tzinfo=timezone.utc),
        "price_current_high":
        None,
        "price_current_low":
        None,
        "price_bid_min":
        10,
        "num_bids":
        0,
    }, {
        "auction_id":
        6,
        "quantity":
        3,
        "price_start":
        10,
        "price_prompt":
        None,
        "price_step_min":
        100,
        "ended":
        False,
        "datetime_end":
        datetime(2000, 6, 7, tzinfo=timezone.utc),
        "price_current_high":
        345,
        "price_current_low":
        None,
        "price_bid_min":
        10,
        "num_bids":
        2,
    }, {
        "auction_id":
        1,
        "quantity":
        1,
        "price_start":
        10,
        "price_prompt":
        None,
        "price_step_min":
        100,
        "ended":
        False,
        "datetime_end":
        datetime(2000, 8, 9, tzinfo=timezone.utc),
        "price_current_high":
        456,
        "price_current_low":
        456,
        "price_bid_min":
        556,
        "num_bids":
        1,
    }, {
        "auction_id":
        2,
        "quantity":
        3,
        "price_start":
        10,
        "price_prompt":
        None,
        "price_step_min":
        100,
        "ended":
        False,
        "datetime_end":
        datetime(2000, 9, 1, tzinfo=timezone.utc),
        "price_current_high":
        567,
        "price_current_low":
        123,
        "price_bid_min":
        223,
        "num_bids":
        3,
    }, {
        "auction_id":
        4,
        "quantity":
        1,
        "price_start":
        10,
        "price_prompt":
        None,
        "price_step_min":
        100,
        "ended":
        False,
        "datetime_end":
        datetime(2000, 10, 2, tzinfo=timezone.utc),
        "price_current_high":
        678,
        "price_current_low":
        678,
        "price_bid_min":
        778,
        "num_bids":
        5,
    }, {
        "auction_id":
        7,
        "quantity":
        5,
        "price_start":
        10,
        "price_prompt":
        None,
        "price_step_min":
        100,
        "ended":
        False,
        "datetime_end":
        datetime(2000, 11, 3, tzinfo=timezone.utc),
        "price_current_high":
        789,
        "price_current_low":
        234,
        "price_bid_min":
        334,
        "num_bids":
        7,
    }]
    for auction in auctions:
        assert auction["datetime_end"].tzinfo == timezone.utc