titan engine, logic model, auth/game/gateway services. csv tables pulled out of the ipa are checked in so it runs out of the box.
90 lines
3.5 KiB
Rust
90 lines
3.5 KiB
Rust
use titan::csv::{ColumnType, CsvNode, CsvReader};
|
|
const SPELLS: &str = concat!(
|
|
"Name,Rarity,Mana,SummonCharacter,Damage,Enabled\n",
|
|
"string,string,int,string,int,boolean\n",
|
|
"Knight,Common,3,Knight,75,true\n",
|
|
",,,,82,\n",
|
|
",,,,90,\n",
|
|
"Archers,Common,3,Archer,42,true\n",
|
|
",,,,46,\n",
|
|
"\"Mini P.E.K.K.A\",Rare,4,MiniPekka,325,false\n"
|
|
);
|
|
#[test]
|
|
fn the_first_two_lines_declare_names_and_types() {
|
|
let table = CsvReader::parse("spells_characters.csv", SPELLS).expect("parse");
|
|
assert_eq!(table.column_count(), 6);
|
|
assert_eq!(table.column_name(0), "Name");
|
|
assert_eq!(table.column_type(0), Some(ColumnType::String));
|
|
assert_eq!(table.column_type(2), Some(ColumnType::Int));
|
|
assert_eq!(table.column_type(5), Some(ColumnType::Boolean));
|
|
assert_eq!(table.column_index("Damage"), Some(4));
|
|
}
|
|
#[test]
|
|
fn a_row_opens_only_when_the_first_column_is_populated() {
|
|
let table = CsvReader::parse("spells_characters.csv", SPELLS).expect("parse");
|
|
assert_eq!(table.row_count(), 3);
|
|
assert_eq!(table.row_at(0).unwrap().string(0), "Knight");
|
|
assert_eq!(table.row_at(1).unwrap().string(0), "Archers");
|
|
assert_eq!(table.row_at(2).unwrap().string(0), "Mini P.E.K.K.A");
|
|
}
|
|
#[test]
|
|
fn continuation_lines_extend_the_per_level_arrays() {
|
|
let table = CsvReader::parse("spells_characters.csv", SPELLS).expect("parse");
|
|
let knight = table.row_at(0).expect("knight");
|
|
assert_eq!(knight.array_size(), 3);
|
|
assert_eq!(knight.value_count(4), 3);
|
|
assert_eq!(knight.int_at(4, 0), 75);
|
|
assert_eq!(knight.int_at(4, 1), 82);
|
|
assert_eq!(knight.int_at(4, 2), 90);
|
|
assert_eq!(knight.scaled_int(4, 9), 90);
|
|
assert_eq!(knight.int(2), 3);
|
|
assert!(knight.boolean(5));
|
|
let archers = table.row_at(1).expect("archers");
|
|
assert_eq!(archers.value_count(4), 2);
|
|
assert!(!table.row_at(2).unwrap().boolean(5));
|
|
}
|
|
#[test]
|
|
fn rows_are_addressable_by_their_first_column() {
|
|
let table = CsvReader::parse("spells_characters.csv", SPELLS).expect("parse");
|
|
assert_eq!(table.row_index_of("Archers"), Some(1));
|
|
assert_eq!(
|
|
table.row_by_name("Mini P.E.K.K.A").map(|row| row.int(2)),
|
|
Some(4)
|
|
);
|
|
assert!(table.row_by_name("Golem").is_none());
|
|
}
|
|
#[test]
|
|
fn quoted_cells_keep_their_commas() {
|
|
let source = concat!(
|
|
"Name,Text\n",
|
|
"string,string\n",
|
|
"Greeting,\"hello, world\"\n",
|
|
"Quote,\"say \"\"hi\"\"\"\n"
|
|
);
|
|
let table = CsvReader::parse("hints.csv", source).expect("parse");
|
|
assert_eq!(table.row_at(0).unwrap().string(1), "hello, world");
|
|
assert_eq!(table.row_at(1).unwrap().string(1), "say \"hi\"");
|
|
}
|
|
#[test]
|
|
fn missing_trailing_cells_decode_as_empty() {
|
|
let source = concat!("Name,A,B\n", "string,int,int\n", "Row,5\n");
|
|
let table = CsvReader::parse("t.csv", source).expect("parse");
|
|
let row = table.row_at(0).expect("row");
|
|
assert_eq!(row.int(1), 5);
|
|
assert_eq!(row.int(2), 0);
|
|
assert!(row.value(2).expect("value").is_empty());
|
|
}
|
|
#[test]
|
|
fn an_unknown_column_type_is_rejected() {
|
|
let source = concat!("Name,A\n", "string,float\n", "Row,1\n");
|
|
let error = CsvReader::parse("bad.csv", source).expect_err("must fail");
|
|
assert!(error.to_string().contains("float"));
|
|
}
|
|
#[test]
|
|
fn a_node_wraps_the_table_with_its_file_identity() {
|
|
let node = CsvNode::load("csv_logic/spells_characters.csv", SPELLS).expect("load");
|
|
assert_eq!(node.name(), "spells_characters");
|
|
assert_eq!(node.file_name(), "csv_logic/spells_characters.csv");
|
|
assert_eq!(node.table().row_count(), 3);
|
|
assert_eq!(node.node_count(), 0);
|
|
}
|