use pretty_assertions::assert_eq;
use vcg_auction::{types::SimpleBid, vcg_auction, vcg_auction_with_tiebreaker};
#[test]
fn vickrey_case() {
let items = vec![("chair".into(), 1)];
let bids = [
vec![SimpleBid::new("Alice", 10, [("chair", 1)])],
vec![SimpleBid::new("Bob", 20, [("chair", 1)])],
];
let result = vcg_auction(&items, &bids).unwrap();
assert_eq!(result.winning_bids, [&bids[1][0]]);
assert_eq!(result.payments, [(&"Bob".into(), 10)]);
}
#[test]
fn simple_case() {
let items = vec![("chair".into(), 2)];
let bids = [
vec![
SimpleBid::new("Alice", 5, [("chair", 1)]),
SimpleBid::new("Alice", 7, [("chair", 2)]),
],
vec![SimpleBid::new("Bob", 4, [("chair", 1)])],
];
let result = vcg_auction(&items, &bids).unwrap();
assert_eq!(result.winning_bids, [&bids[0][0], &bids[1][0]]);
assert_eq!(result.payments, [(&"Alice".into(), 0), (&"Bob".into(), 2)]);
}
#[test]
fn non_exclusive_bids() {
let items = vec![("chair".into(), 1), ("table".into(), 1)];
let bids = vec![
vec![SimpleBid::new("Alice", 5, [("chair", 1)])],
vec![SimpleBid::new("Alice", 10, [("table", 1)])],
vec![SimpleBid::new("Bob", 20, [("chair", 1), ("table", 1)])],
];
let result = vcg_auction(&items, &bids).unwrap();
assert_eq!(result.winning_bids, [&bids[2][0]]);
assert_eq!(result.payments, [(&"Bob".into(), 15)]);
}
#[test]
fn wikipedia_example() {
let items = vec![("apple".into(), 2)];
let bids = vec![
vec![SimpleBid::new("Alice", 5, [("apple", 1)])],
vec![SimpleBid::new("Bob", 2, [("apple", 1)])],
vec![SimpleBid::new("Carol", 6, [("apple", 2)])],
];
let result = vcg_auction(&items, &bids).unwrap();
assert_eq!(result.winning_bids, [&bids[0][0], &bids[1][0]]);
assert_eq!(result.payments, [(&"Alice".into(), 4), (&"Bob".into(), 1)]);
}
#[test]
fn mutually_exclusive_bidders() {
let items = vec![("chair".into(), 2)];
let bids = vec![
vec![SimpleBid::new("Alice", 5, [("chair", 1)])],
vec![
SimpleBid::new("Bob", 4, [("chair", 1)]),
SimpleBid::new("Carol", 3, [("chair", 1)]),
],
];
let result = vcg_auction(&items, &bids).unwrap();
assert_eq!(result.winning_bids, [&bids[0][0], &bids[1][0]]);
assert_eq!(result.payments, [(&"Alice".into(), 0), (&"Bob".into(), 3)]);
}
#[test]
fn no_valid_bids() {
let items = vec![("apple".into(), 2)];
let no_bid_cases: &[Vec<Vec<SimpleBid>>] = &[
vec![],
vec![vec![]],
vec![vec![], vec![]],
vec![vec![SimpleBid::new("Alice", 5, [("apple", 3)])]],
];
for no_bid_case in no_bid_cases {
let result = vcg_auction(&items, no_bid_case).unwrap();
assert!(result.winning_bids.is_empty());
assert!(result.payments.is_empty());
}
}
#[test]
fn simple_tiebreaker() {
let items = vec![("chair".into(), 1)];
let bids = vec![
vec![SimpleBid::new("Alice", 10, vec![("chair", 1)])],
vec![SimpleBid::new("Bob", 10, vec![("chair", 1)])],
];
let tiebreak = |_: &[Vec<&SimpleBid>]| 1;
let result = vcg_auction_with_tiebreaker(&items, &bids, tiebreak).unwrap();
assert_eq!(result.winning_bids, [&bids[1][0]]);
assert_eq!(result.payments, [(&"Bob".into(), 10),]);
}
#[test]
fn unrelated_bids_same_bidder() {
let items = vec![("chair".into(), 2), ("table".into(), 1)];
let bids = vec![
vec![SimpleBid::new("Alice", 10, vec![("chair", 2)])],
vec![SimpleBid::new("Alice", 5, vec![("table", 1)])],
vec![SimpleBid::new("Bob", 4, vec![("table", 1)])],
];
let result = vcg_auction(&items, &bids).unwrap();
assert_eq!(result.winning_bids, [&bids[0][0], &bids[1][0]]);
assert_eq!(result.payments, [(&"Alice".into(), 4),]);
}