Skip to content

Commit

Permalink
Merge pull request #43 from lykia-rs/feature/planner
Browse files Browse the repository at this point in the history
More test coverage
  • Loading branch information
can-keklik authored Dec 6, 2024
2 parents 82e57f1 + 0e819e9 commit 49928c5
Show file tree
Hide file tree
Showing 11 changed files with 460 additions and 52 deletions.
17 changes: 9 additions & 8 deletions lykiadb-lang/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ impl<'a> Parser<'a> {

fn expect_get_path(&mut self, initial: Box<Expr>, tok: TokenType) -> ParseResult<Box<Expr>> {
let mut expr = initial;

loop {
if self.match_next(&sym!(LeftParen)) {
expr = self.finish_call(expr)?;
Expand All @@ -600,7 +600,7 @@ impl<'a> Parser<'a> {
} else {
break;
}
};
}

Ok(expr)
}
Expand All @@ -609,11 +609,12 @@ impl<'a> Parser<'a> {
let expr = self.primary()?;

if let Expr::Variable { name, span, id } = expr.as_ref() {
if !name.dollar
{
if !name.dollar {
let next_tok = &self.peek_bw(0).tok_type;

if (next_tok == &sym!(Dot) || next_tok != &sym!(LeftParen)) && self.in_select_depth > 0 {
if (next_tok == &sym!(Dot) || next_tok != &sym!(LeftParen))
&& self.in_select_depth > 0
{
let head = name.clone();
let mut tail: Vec<crate::Identifier> = vec![];
while self.match_next(&sym!(Dot)) {
Expand All @@ -628,11 +629,11 @@ impl<'a> Parser<'a> {
}));
}

return Ok(self.expect_get_path(expr, sym!(DoubleColon))?);
return self.expect_get_path(expr, sym!(DoubleColon));
}
}

Ok(self.expect_get_path(expr, sym!(Dot))?)
self.expect_get_path(expr, sym!(Dot))
}

fn finish_call(&mut self, callee: Box<Expr>) -> ParseResult<Box<Expr>> {
Expand Down Expand Up @@ -777,7 +778,7 @@ impl<'a> Parser<'a> {
}

fn expected(&mut self, expected_tok_type: &TokenType) -> ParseResult<&Token> {
if self.cmp_tok(&expected_tok_type) {
if self.cmp_tok(expected_tok_type) {
return Ok(self.advance());
};
let prev_token = self.peek_bw(1);
Expand Down
2 changes: 1 addition & 1 deletion lykiadb-lang/src/tokenizer/scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ impl<'a> Scanner<'a> {

fn scan_double_token(&mut self, start: usize, c: char) -> Token {
self.advance();

if self.match_next(':') && c == ':' {
Token {
tok_type: sym!(DoubleColon),
Expand Down
14 changes: 13 additions & 1 deletion lykiadb-server/src/engine/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,12 @@ pub struct Output {
out: Vec<RV>,
}

impl Default for Output {
fn default() -> Self {
Self::new()
}
}

impl Output {
pub fn new() -> Output {
Output { out: Vec::new() }
Expand All @@ -685,7 +691,13 @@ impl Output {
}
// TODO(vck): Remove this
pub fn expect_str(&mut self, rv: Vec<String>) {
assert_eq!(self.out.iter().map(|x| x.to_string()).collect::<Vec<String>>(), rv)
assert_eq!(
self.out
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>(),
rv
)
}
}

Expand Down
64 changes: 41 additions & 23 deletions lykiadb-server/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ impl Runtime {
}

pub mod test_helpers {
use pretty_assertions::assert_eq;
use std::collections::HashMap;
use std::sync::Arc;
use pretty_assertions::assert_eq;

use crate::engine::{Runtime, RuntimeMode, Interpreter, error::ExecutionError};
use crate::engine::{error::ExecutionError, Interpreter, Runtime, RuntimeMode};
use crate::util::{alloc_shared, Shared};
use crate::value::RV;

Expand All @@ -60,21 +60,26 @@ pub mod test_helpers {
runtime: Runtime,
}

impl Default for RuntimeTester {
fn default() -> Self {
Self::new()
}
}

impl RuntimeTester {
pub fn new() -> RuntimeTester {
let out = alloc_shared(Output::new());

RuntimeTester {
RuntimeTester {
out: out.clone(),
runtime: Runtime::new(RuntimeMode::File, Interpreter::new(Some(out), true)),
runtime: Runtime::new(RuntimeMode::File, Interpreter::new(Some(out), true)),
}
}

pub fn test_file(input: &str) {
let parts: Vec<&str> = input.split("#[").collect();

for part in parts[1..].iter() {

let mut tester = RuntimeTester::new();

let directives_and_input = part.trim();
Expand Down Expand Up @@ -111,37 +116,50 @@ pub mod test_helpers {
}

fn run_case(&mut self, case_parts: Vec<String>, flags: HashMap<&str, &str>) {

assert!(case_parts.len() > 1, "Expected at least one input/output pair");

assert!(
case_parts.len() > 1,
"Expected at least one input/output pair"
);

let mut errors: Vec<ExecutionError> = vec![];

let result = self.runtime.interpret(&case_parts[0]);

if let Err(err) = result {
errors.push(err);
}

for part in &case_parts[1..] {
if part.starts_with("err") {
assert_eq!(errors.iter().map(|x| x.to_string()).collect::<Vec<String>>().join("\n"), part[3..].trim());
}

else if part.starts_with(">") {
assert_eq!(
errors
.iter()
.map(|x| x.to_string())
.collect::<Vec<String>>()
.join("\n"),
part[3..].trim()
);
} else if part.starts_with('>') {
let result = self.runtime.interpret(part[1..].trim());

if let Err(err) = result {
errors.push(err);
}
}
else if flags.get("run") == Some(&"plan") {
} else if flags.get("run") == Some(&"plan") {
// TODO(vck): Remove this
self.out.write().unwrap().expect(vec![RV::Str(Arc::new(part.to_string()))]);
self.out
.write()
.unwrap()
.expect(vec![RV::Str(Arc::new(part.to_string()))]);
} else {
self.out.write().unwrap().expect_str(
part.to_string()
.split('\n')
.map(|x| x.to_string())
.collect(),
);
}
else {
self.out.write().unwrap().expect_str(part.to_string().split("\n").map(|x| x.to_string()).collect());
}
}
}
}
}
}
76 changes: 76 additions & 0 deletions lykiadb-server/src/engine/stdlib/fib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,79 @@ pub fn nt_fib(_interpreter: &mut Interpreter, args: &[RV]) -> Result<RV, HaltRea
.into(),
))
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_basic_fibonacci() {
let mut interpreter = Interpreter::new(None, true);

// Test first few Fibonacci numbers
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(0.0)]).unwrap(),
RV::Num(0.0)
);
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(1.0)]).unwrap(),
RV::Num(1.0)
);
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(2.0)]).unwrap(),
RV::Num(1.0)
);
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(3.0)]).unwrap(),
RV::Num(2.0)
);
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(4.0)]).unwrap(),
RV::Num(3.0)
);
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(5.0)]).unwrap(),
RV::Num(5.0)
);
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(6.0)]).unwrap(),
RV::Num(8.0)
);
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(7.0)]).unwrap(),
RV::Num(13.0)
);
}

#[test]
fn test_invalid_input() {
let mut interpreter = Interpreter::new(None, true);

// Test with non-numeric input
let result = nt_fib(&mut interpreter, &[RV::Bool(true)]);
assert!(result.is_err());

let err = result.unwrap_err();
match err {
HaltReason::Error(e) => {
assert!(e.to_string().contains("Unexpected argument"));
}
_ => panic!("Expected InterpretError"),
}
}

#[test]
fn test_negative_input() {
let mut interpreter = Interpreter::new(None, true);

// Negative numbers should return themselves as per implementation
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(-1.0)]).unwrap(),
RV::Num(-1.0)
);
assert_eq!(
nt_fib(&mut interpreter, &[RV::Num(-5.0)]).unwrap(),
RV::Num(-5.0)
);
}
}
Loading

0 comments on commit 49928c5

Please sign in to comment.