rink-rs/tests/query.rs
2018-11-15 18:55:45 +01:00

350 lines
9 KiB
Rust

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
extern crate rink;
use rink::*;
thread_local! {
static CONTEXT: Context = {
let mut ctx = load().unwrap();
ctx.use_humanize = false;
ctx
};
}
fn test(input: &str, output: &str) {
let mut iter = text_query::TokenIterator::new(input.trim()).peekable();
let expr = text_query::parse_query(&mut iter);
CONTEXT.with(|ctx| {
let res = ctx.eval_outer(&expr);
let res = match res {
Ok(v) => v.to_string(),
Err(v) => v.to_string()
};
assert_eq!(res, output);
});
}
#[test]
fn test_definition() {
test("watt", "Definition: watt = J / s = 1 watt (power; kg m^2 / s^3)");
}
#[test]
fn test_eval() {
test("5 inch", "127 millimeter (length)");
}
#[test]
fn test_convert() {
test("5 inch -> cm", "12.7 centimeter (length)");
}
#[test]
fn test_temp() {
test("2 degC 2 -> degC", "277.15 °C (temperature)");
}
#[test]
fn test_determinism() {
test("weber / m", "1 meter tesla");
}
#[test]
fn test_sqrt_errors() {
test("sqrt -1",
"Complex numbers are not implemented: sqrt(-1 (dimensionless))");
test("sqrt(2m)",
"Result must have integer dimensions: sqrt(2 meter (length))");
}
#[test]
fn test_number_regress() {
test("953 mega",
"9.53e8 (dimensionless)");
}
#[test]
fn test_lookup() {
test("pcs", "Definition: parsec = approx. 32.31314 petameter (length; m)");
}
#[test]
fn test_consts_in_conversion() {
test("1/mpg -> L / 100km", "112903/480, approx. 235.2145 liter / 100 kilometer (area)");
}
#[test]
fn negative_prefixes() {
test("-1ms", "-1 millisecond (time)");
}
#[test]
fn negative_now() {
test("-#jan 01, 1970#", "Operation is not defined: - <1970-01-01 00:00:00 +00:00>");
}
#[test]
fn negative_conversion() {
test("1 m -> -meter", "-1 * -1 meter (length)");
}
#[test]
fn test_units_for() {
test("units for electrical_potential",
"Units for kg m^2 / A s^3 (electrical_potential): \
CGS Units: abvolt, daniell, intvolt, statvolt; SI Derived Units: volt");
}
#[test]
fn test_factorize() {
test("factorize velocity",
"Factorizations: velocity; acceleration time; \
flow_rate fuel_efficiency; \
frequency length; jerk time^2");
}
#[test]
fn test_conformance() {
test(
"W -> J",
"Conformance error: 1 watt (power) != 1 joule (energy)\n\
Suggestions: multiply left side by time, multiply right side by frequency",
);
test(
"W/s -> J^2",
"Conformance error: 1 newton^2 / kilogram != 1 joule^2\n\
Suggestions: multiply left side by moment_of_inertia, divide right side by moment_of_inertia",
);
test(
"m^2 -> kg^2",
"Conformance error: 1 meter^2 (area) != 1 kilogram^2 (kg^2)\n\
Suggestions: multiply left side by linear_density^2, multiply right side by area / mass^2",
);
test(
"c -> kg",
"Conformance error: 299792458 meter / second (velocity) != 1 kilogram (mass)\n\
Suggestions: multiply left side by mass time / length, multiply right side by length / mass time"
);
test(
"1/m -> 'abc'",
"Conformance error: 1 / meter (m^-1) != 1 abc (abc)\n\
Suggestions: multiply left side by 'abc' length, divide right side by 'abc' length",
);
}
#[test]
fn test_dates() {
test("#jan 01, 1970#",
"1970-01-01 00:00:00 +00:00");
}
#[test]
fn test_lists() {
test("pi hour -> hr;min;sec", "3 hour, 8 minute, 29.73355 second (time)");
test("meter -> ft;inch;line", "3 foot, 3 inch, 4.440944 line (length)");
}
#[test]
fn test_volume_prefix() {
test("mm^3", "1 millimeter^3 (volume)");
test("1000000 m^2", "1 kilometer^2 (area)");
}
#[test]
fn test_offset_conversion() {
test("#jan 01, 1970# -> -05:00",
"1969-12-31 19:00:00 -05:00");
}
#[test]
fn test_time_hms() {
test("ks", "16 minute, 40 second (time)");
test("nanosecond", "1 nanosecond (time)");
}
#[test]
fn test_bases() {
test("pi -> hex", "approx. 3.243f6a (dimensionless)");
test("pi -> oct", "approx. 3.110375 (dimensionless)");
test("pi -> bin", "approx. 11.00100 (dimensionless)");
test("pi m -> hex m", "approx. 3.243f6a meter (length)");
test("pi m -> oct m", "approx. 3.110375 meter (length)");
test("pi m -> bin m", "approx. 11.00100 meter (length)");
test("100K -> hex °C", "Conversion to °C is not defined in base 16");
test("now -> hex +00:00", "Conversion to 00:00 is not defined in base 16");
test("256 -> base 16", "100 (dimensionless)");
}
#[test]
fn test_typos() {
test("rsi", "No such unit rsi, did you mean RSI?");
}
#[test]
fn test_convert_from_substances() {
test("density of water",
"1000 kilogram / meter^3 (density)");
test("mass of ml water",
"1 gram (mass)");
test("volume of g water",
"1000 millimeter^3 (volume)");
test("ml water -> g",
"water: volume = 1000 millimeter^3; mass = 1 gram");
test("g water -> ml",
"water: mass = 1 gram; \
volume = 1 milliliter");
}
#[test]
fn test_convert_to_substances() {
test("kg -> egg",
"egg: USA large egg. \
mass = 1 kilogram; \
egg_shelled = 20 egg; \
egg_white = 100/3, approx. 33.33333 egg; \
egg_yolk = 5000/93, approx. 53.76344 egg");
}
#[test]
fn test_substance_add() {
test("air",
"air: Average molecular weight of air. \
molar_mass = approx. 28.96790 gram / mole");
}
#[test]
fn test_duration_add() {
test("#jan 01, 1970# + 1 s",
"1970-01-01 00:00:01 +00:00");
test("#jan 01, 1970# + 1.123 s",
"1970-01-01 00:00:01.123 +00:00");
}
#[test]
fn test_0_seconds() {
test("0 s", "0 second (time)");
}
#[test]
fn right_hand_property() {
test("kg -> mass_shelled of egg",
"20 egg_shelled (mass)");
test("nauticalmile -> arcmin radius of earth / radian",
"approx. 0.9993245 arcmin earth_radius / radian (length)");
}
#[test]
fn percent_operator() {
test("100%", "1 (dimensionless)");
test("100%%", "0.01 (dimensionless)");
test("200% ** 2", "4 (dimensionless)");
test("120% 2", "2.4 (dimensionless)");
test("% 1", "0.01 (dimensionless)");
}
#[test]
fn test_kilosecond() {
test("1ks", "16 minute, 40 second (time)");
test("1kss", "16 minute, 40 second (time)");
}
#[test]
#[should_panic]
fn test_second_double_prefix() {
let mut iter = text_query::TokenIterator::new("mks").peekable();
let expr = text_query::parse_query(&mut iter);
CONTEXT.with(|ctx| {
ctx.eval_outer(&expr).unwrap();
});
}
#[test]
fn test_missing_substance() {
test(
"density of flubber",
"No such unit flubber, did you mean flour?",
);
}
#[test]
fn test_missing_property() {
test("mass of flour", "No such property mass of flour");
}
#[test]
fn test_unary_operators() {
test("+--+42", "42 (dimensionless)");
test("++-+42", "-42 (dimensionless)");
}
#[test]
fn test_equals() {
test("a = kg N / W^2", "1 second^2 / gray meter");
test(
"1 = kg",
"= is currently only used for inline unit definitions: expected unit, got 1",
);
}
#[test]
fn mismatched_units() {
test(
"W - kg",
"Subtraction of units with mismatched units is not meaningful: \
<1 watt (power)> - <1 kilogram (mass)>",
);
}
#[test]
fn temperature_with_dimension() {
test("kg °C", "Expected dimensionless, got: <1 kilogram (mass)>");
}
#[test]
fn test_functions() {
test("exp(ln(10))", "approx. 10.00000 (dimensionless)");
test("log2(65536)", "approx. 16 (dimensionless)");
test("10^log10(123)", "approx. 123.0000 (dimensionless)");
test("log(27, 3)", "approx. 3 (dimensionless)");
test("sin(pi/2)", "approx. 1 (dimensionless)");
test("cos(asin(0.5) - pi/2)", "approx. 0.5000000 (dimensionless)");
test("atan(tan(0.42))", "approx. 0.4199999 (dimensionless)");
test("acos(1)", "approx. 0 (dimensionless)");
test("acosh(cosh(1))", "approx. 1 (dimensionless)");
test("asinh(sinh(0.123))", "approx. 0.1230000 (dimensionless)");
test("atanh(tanh(1.23))", "approx. 1.230000 (dimensionless)");
test("hypot(3 m, 4 m)", "approx. 5 meter (length)");
test("atan2(7, 6)", "approx. 0.8621700 (dimensionless)");
}
#[test]
fn test_equal_rhs() {
test("1 -> a=3", "1/3, approx. 0.3333333 a (dimensionless)");
}
#[test]
fn test_pow_with_dimension() {
test(
"2^m",
"Exponent must be dimensionless: <2 (dimensionless)> ^ <1 meter (length)>",
);
}
#[test]
fn test_reciprocal_conversion() {
test(
"miles / gallon -> l / 100km",
"Conformance error: approx. 425143.7 / meter^2 (fuel_efficiency) != 10000 micrometer^2 (area)\n\
Suggestions: Reciprocal conversion, invert one side",
);
}
#[test]
fn test_non_conversion_input() {
test("g", "Definition: gram = (1 / 1000) kg = 1 gram (mass; kg)");
}