Merge pull request #866 from Skgland/add_tests
Add tests for some recently closed Issues
This commit is contained in:
89
Cargo.lock
generated
89
Cargo.lock
generated
@@ -9,6 +9,20 @@ dependencies = [
|
||||
"nodrop",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "assert_cmd"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2475b58cd94eb4f70159f4fd8844ba3b807532fe3131b3373fae060bbe30396"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"doc-comment",
|
||||
"predicates",
|
||||
"predicates-core",
|
||||
"predicates-tree",
|
||||
"wait-timeout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
@@ -87,6 +101,17 @@ dependencies = [
|
||||
"byte-tools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.0"
|
||||
@@ -206,6 +231,12 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "difference"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
@@ -242,6 +273,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc9f8914dcb99891bdfee82536bbff8d9aa612b0dbe83872afbc66902bdec0b9"
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "downcast"
|
||||
version = "0.10.0"
|
||||
@@ -851,6 +888,32 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||
|
||||
[[package]]
|
||||
name = "predicates"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eeb433456c1a57cc93554dea3ce40b4c19c4057e41c55d4a0f3d84ea71c325aa"
|
||||
dependencies = [
|
||||
"difference",
|
||||
"predicates-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates-core"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57e35a3326b75e49aa85f5dc6ec15b41108cf5aee58eabb1f274dd18b73c2451"
|
||||
|
||||
[[package]]
|
||||
name = "predicates-tree"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15f553275e5721409451eb85e15fd9a860a6e5ab4496eb215987502b5f5391f2"
|
||||
dependencies = [
|
||||
"predicates-core",
|
||||
"treeline",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
@@ -1091,6 +1154,15 @@ version = "0.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6"
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
@@ -1202,6 +1274,7 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
name = "scryer-prolog"
|
||||
version = "0.8.128"
|
||||
dependencies = [
|
||||
"assert_cmd",
|
||||
"base64",
|
||||
"blake2",
|
||||
"chrono",
|
||||
@@ -1220,6 +1293,7 @@ dependencies = [
|
||||
"num-rug-adapter",
|
||||
"openssl",
|
||||
"ordered-float",
|
||||
"predicates-core",
|
||||
"prolog_parser",
|
||||
"ref_thread_local",
|
||||
"ring",
|
||||
@@ -1492,6 +1566,12 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "treeline"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.12.0"
|
||||
@@ -1571,6 +1651,15 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
|
||||
@@ -52,3 +52,7 @@ roxmltree = "0.11.0"
|
||||
base64 = "0.12.3"
|
||||
sodiumoxide = "0.2.6"
|
||||
slice-deque = "0.3.0"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = "1.0.3"
|
||||
predicates-core = "1.0.2"
|
||||
|
||||
@@ -365,7 +365,17 @@ impl Stream {
|
||||
}
|
||||
|
||||
pub fn bytes(&self) -> Option<std::cell::Ref<Vec<u8>>> {
|
||||
// if Ref had an and_then function this could be simplified
|
||||
/*
|
||||
// Replacement of workaround for when we have stable https://github.com/rust-lang/rust/issues/81061
|
||||
std::cell::Ref::filter_map(
|
||||
self.stream_inst.0.borrow(),
|
||||
|inner_stream| match inner_stream.stream_inst {
|
||||
StreamInstance::Bytes(cursor) => Some(cursor.get_ref()),
|
||||
_ => None,
|
||||
},
|
||||
)
|
||||
.ok()
|
||||
*/
|
||||
let val = std::cell::Ref::map(self.stream_inst.0.borrow(), |inner_stream| {
|
||||
&inner_stream.stream_inst
|
||||
});
|
||||
|
||||
4
tests-pl/issue812-singleton-warning.pl
Normal file
4
tests-pl/issue812-singleton-warning.pl
Normal file
@@ -0,0 +1,4 @@
|
||||
% hello
|
||||
% line!
|
||||
|
||||
a :- b(X).
|
||||
3
tests-pl/issue820-goals.pl
Normal file
3
tests-pl/issue820-goals.pl
Normal file
@@ -0,0 +1,3 @@
|
||||
test :- write(world), nl.
|
||||
|
||||
:- initialization(write(hello)).
|
||||
1
tests-pl/issue831-call0.pl
Normal file
1
tests-pl/issue831-call0.pl
Normal file
@@ -0,0 +1 @@
|
||||
:- initialization(call).
|
||||
1
tests-pl/issue839-op3.pl
Normal file
1
tests-pl/issue839-op3.pl
Normal file
@@ -0,0 +1 @@
|
||||
:- op(900, fy, [$,@]).
|
||||
3
tests-pl/issue841-occure-check.pl
Normal file
3
tests-pl/issue841-occure-check.pl
Normal file
@@ -0,0 +1,3 @@
|
||||
:- set_prolog_flag(occurs_check, true).
|
||||
|
||||
f(X, g(X)).
|
||||
1
tests-pl/issue852-throw_e.pl
Normal file
1
tests-pl/issue852-throw_e.pl
Normal file
@@ -0,0 +1 @@
|
||||
:- initialization(throw(e)).
|
||||
6
tests-pl/syntax_error.pl
Normal file
6
tests-pl/syntax_error.pl
Normal file
@@ -0,0 +1,6 @@
|
||||
:- use_module(library(debug)).
|
||||
:- use_module(library(format)).
|
||||
|
||||
missing_dot :- write('No "." at the end of the line'), nl
|
||||
|
||||
:- initialization(missing_dot).
|
||||
@@ -1,66 +0,0 @@
|
||||
/// Loads the file and if some expected output is given checks that it matches
|
||||
fn test_file(file: &str, expected: Option<&[u8]>) {
|
||||
use scryer_prolog::*;
|
||||
|
||||
let input = machine::Stream::from("");
|
||||
let output = machine::Stream::from(String::new());
|
||||
|
||||
let mut wam = machine::Machine::new(input, output.clone());
|
||||
|
||||
wam.load_file(
|
||||
file.into(),
|
||||
machine::Stream::from(
|
||||
std::fs::read_to_string(AsRef::<std::path::Path>::as_ref(file)).unwrap(),
|
||||
),
|
||||
);
|
||||
|
||||
if let Some(expected) = expected {
|
||||
let output = output.bytes().unwrap();
|
||||
assert_eq!(output.as_slice(), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtins() {
|
||||
test_file("src/tests/builtins.pl", Some(b""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_with_inference_limit() {
|
||||
test_file("src/tests/call_with_inference_limit.pl", Some(b""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn facts() {
|
||||
test_file("src/tests/facts.pl", Some(b""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hello_world() {
|
||||
test_file(
|
||||
"src/tests/hello_world.pl",
|
||||
Some("Hello World!\n".as_bytes()),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicates() {
|
||||
test_file("src/tests/predicates.pl", Some(b""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rules() {
|
||||
test_file("src/tests/rules.pl", Some(b""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // ignored as this does not appear to terminate
|
||||
fn setup_call_cleanup() {
|
||||
test_file("src/tests/setup_call_cleanup.pl", Some(b""));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // ignored as this does not terminate
|
||||
fn clpz() {
|
||||
test_file("src/tests/clpz/test_clpz.pl", Some(b""));
|
||||
}
|
||||
84
tests/scryer/helper.rs
Normal file
84
tests/scryer/helper.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use assert_cmd::Command;
|
||||
use std::ffi::OsStr;
|
||||
|
||||
pub(crate) trait Expectable {
|
||||
#[track_caller]
|
||||
fn assert_eq(self, other: &[u8]);
|
||||
}
|
||||
|
||||
impl Expectable for &str {
|
||||
#[track_caller]
|
||||
fn assert_eq(self, other: &[u8]) {
|
||||
if let Ok(other_str) = std::str::from_utf8(other) {
|
||||
assert_eq!(other_str, self)
|
||||
} else {
|
||||
// should always fail as other is not valid utf-8 but self is
|
||||
// just for consistent assert error message
|
||||
assert_eq!(other, self.as_bytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Expectable for &[u8] {
|
||||
#[track_caller]
|
||||
fn assert_eq(self, other: &[u8]) {
|
||||
assert_eq!(other, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Tests whether the file can be successfully loaded
|
||||
/// and produces the expected output during it
|
||||
pub(crate) fn load_module_test<T: Expectable>(file: &str, expected: T) {
|
||||
use scryer_prolog::*;
|
||||
|
||||
let input = machine::Stream::from("");
|
||||
let output = machine::Stream::from(String::new());
|
||||
|
||||
let mut wam = machine::Machine::new(input, output.clone());
|
||||
|
||||
wam.load_file(
|
||||
file.into(),
|
||||
machine::Stream::from(
|
||||
std::fs::read_to_string(AsRef::<std::path::Path>::as_ref(file)).unwrap(),
|
||||
),
|
||||
);
|
||||
|
||||
let output = output.bytes().unwrap();
|
||||
expected.assert_eq(output.as_slice());
|
||||
}
|
||||
|
||||
pub const SCRYER_PROLOG: &str = "scryer-prolog";
|
||||
|
||||
pub fn run_top_level_test_no_args<
|
||||
S: Into<Vec<u8>>,
|
||||
O: assert_cmd::assert::IntoOutputPredicate<P>,
|
||||
P: predicates_core::Predicate<[u8]>,
|
||||
>(
|
||||
stdin: S,
|
||||
expected_stdout: O,
|
||||
) {
|
||||
run_top_level_test_with_args::<&[&str], _, _, _, _>(&[], stdin, expected_stdout)
|
||||
}
|
||||
|
||||
/// Test whether scryer-prolog
|
||||
/// produces the expected output when called with the supplied
|
||||
/// arguments and fed the supplied input
|
||||
pub fn run_top_level_test_with_args<
|
||||
A: IntoIterator<Item = AS>,
|
||||
S: Into<Vec<u8>>,
|
||||
O: assert_cmd::assert::IntoOutputPredicate<P>,
|
||||
AS: AsRef<OsStr>,
|
||||
P: predicates_core::Predicate<[u8]>,
|
||||
>(
|
||||
args: A,
|
||||
stdin: S,
|
||||
expected_stdout: O,
|
||||
) {
|
||||
Command::cargo_bin(SCRYER_PROLOG)
|
||||
.unwrap()
|
||||
.args(args)
|
||||
.write_stdin(stdin)
|
||||
.assert()
|
||||
.stdout(expected_stdout.into_output())
|
||||
.success();
|
||||
}
|
||||
163
tests/scryer/issues.rs
Normal file
163
tests/scryer/issues.rs
Normal file
@@ -0,0 +1,163 @@
|
||||
use crate::helper::{load_module_test, run_top_level_test_no_args, run_top_level_test_with_args};
|
||||
|
||||
// issue #857
|
||||
#[test]
|
||||
fn display_constraints() {
|
||||
run_top_level_test_no_args(
|
||||
"\
|
||||
X = 1.\n\
|
||||
use_module(library(dif)).\n\
|
||||
X = 1.\n\
|
||||
dif(X,1).\n",
|
||||
" \
|
||||
X = 1.\n \
|
||||
true.\n \
|
||||
X = 1.\n \
|
||||
dif:dif(X,1).\n\
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
// issue #852
|
||||
#[test]
|
||||
fn do_not_duplicate_path_components() {
|
||||
run_top_level_test_no_args(
|
||||
"\
|
||||
['tests-pl/issue852-throw_e.pl'].\n\
|
||||
['tests-pl/issue852-throw_e.pl'].\n\
|
||||
",
|
||||
"\
|
||||
caught: e\n\
|
||||
false.\n\
|
||||
Warning: overwriting $initialization_goals/1\n\
|
||||
caught: e\n\
|
||||
false.\n\
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
// issue #844
|
||||
#[test]
|
||||
fn handle_residual_goal() {
|
||||
run_top_level_test_no_args(
|
||||
"\
|
||||
use_module(library(dif)).\n\
|
||||
use_module(library(atts)).\n\
|
||||
-X\\=X.\n\
|
||||
-X=X.\n\
|
||||
dif(-X,X).\n\
|
||||
dif(-X,X), -X=X.\n\
|
||||
call_residue_vars(dif(-X,X), Vars).\n\
|
||||
set_prolog_flag(occurs_check, true).\n\
|
||||
-X\\=X.\n\
|
||||
dif(-X,X).\n\
|
||||
",
|
||||
" \
|
||||
true.\n \
|
||||
true.\n\
|
||||
false.\n \
|
||||
X = - X.\n \
|
||||
dif:dif(- X,X).\n\
|
||||
false.\n \
|
||||
Vars = [X], dif:dif(- X,X).\n \
|
||||
true.\n \
|
||||
true.\n \
|
||||
true.\n\
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
// issue #841
|
||||
#[test]
|
||||
fn occurs_check_flag() {
|
||||
run_top_level_test_with_args(
|
||||
&["tests-pl/issue841-occure-check.pl"],
|
||||
"\
|
||||
f(X, X).\n\
|
||||
",
|
||||
"false.\n",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn occurs_check_flag2() {
|
||||
run_top_level_test_no_args(
|
||||
"\
|
||||
set_prolog_flag(occurs_check, true).\n\
|
||||
X = -X.\n\
|
||||
asserta(f(X,g(X))).\n\
|
||||
f(X,X).\n\
|
||||
X-X = X-g(X).
|
||||
",
|
||||
" \
|
||||
true.\n\
|
||||
false.\n \
|
||||
true.\n\
|
||||
false.\n\
|
||||
false.\n\
|
||||
",
|
||||
)
|
||||
}
|
||||
|
||||
// issue #839
|
||||
#[test]
|
||||
fn op3() {
|
||||
run_top_level_test_with_args(&["tests-pl/issue839-op3.pl"], "", "")
|
||||
}
|
||||
|
||||
// issue #820
|
||||
#[test]
|
||||
fn multiple_goals() {
|
||||
run_top_level_test_with_args(
|
||||
&["-g", "test", "-g", "halt", "tests-pl/issue820-goals.pl"],
|
||||
"",
|
||||
"helloworld\n",
|
||||
);
|
||||
}
|
||||
|
||||
// issue #820
|
||||
#[test]
|
||||
fn compound_goal() {
|
||||
run_top_level_test_with_args(
|
||||
&["-g", "test,halt", "tests-pl/issue820-goals.pl"],
|
||||
"",
|
||||
"helloworld\n",
|
||||
)
|
||||
}
|
||||
|
||||
// issue #815
|
||||
#[test]
|
||||
fn no_stutter() {
|
||||
run_top_level_test_no_args("write(a), write(b), false.\n", "abfalse.\n")
|
||||
}
|
||||
|
||||
// issue #812
|
||||
#[test]
|
||||
#[ignore] // FIXME: line is of by one, empty line not accounted for or starting to count at line 0?
|
||||
fn singleton_warning() {
|
||||
run_top_level_test_no_args(
|
||||
"['tests-pl/issue812-singleton-warning.pl'].",
|
||||
"\
|
||||
Warning: singleton variables X at line 4 of issue812-singleton-warning.pl\n \
|
||||
true.\n\
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
// issue #807
|
||||
#[test]
|
||||
fn ignored_constraint() {
|
||||
run_top_level_test_no_args(
|
||||
"use_module(library(freeze)), freeze(X,false), X \\=a.",
|
||||
" freeze:freeze(X,user:false).\n",
|
||||
);
|
||||
}
|
||||
|
||||
// issue #831
|
||||
#[test]
|
||||
fn call_0() {
|
||||
load_module_test(
|
||||
"tests-pl/issue831-call0.pl",
|
||||
"caught: error(existence_error(procedure,call/0),call/0)\n",
|
||||
);
|
||||
}
|
||||
4
tests/scryer/main.rs
Normal file
4
tests/scryer/main.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
mod helper;
|
||||
|
||||
mod issues;
|
||||
mod src_tests;
|
||||
59
tests/scryer/src_tests.rs
Normal file
59
tests/scryer/src_tests.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
use crate::helper::{load_module_test, run_top_level_test_with_args};
|
||||
|
||||
#[test]
|
||||
fn builtins() {
|
||||
load_module_test("src/tests/builtins.pl", "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_with_inference_limit() {
|
||||
load_module_test("src/tests/call_with_inference_limit.pl", "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn facts() {
|
||||
load_module_test("src/tests/facts.pl", "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hello_world() {
|
||||
load_module_test("src/tests/hello_world.pl", "Hello World!\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn syntax_error() {
|
||||
load_module_test(
|
||||
"tests-pl/syntax_error.pl",
|
||||
"caught: error(syntax_error(incomplete_reduction),read_term/3:6)\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn predicates() {
|
||||
load_module_test("src/tests/predicates.pl", "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rules() {
|
||||
load_module_test("src/tests/rules.pl", "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn setup_call_cleanup_load() {
|
||||
load_module_test("src/tests/setup_call_cleanup.pl", "caught: unthrown\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn setup_call_cleanup_process() {
|
||||
run_top_level_test_with_args(
|
||||
&["src/tests/setup_call_cleanup.pl"],
|
||||
"",
|
||||
"caught: unthrown\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // ignored as this does not terminate
|
||||
fn clpz_load() {
|
||||
load_module_test("src/tests/clpz/test_clpz.pl", "");
|
||||
}
|
||||
Reference in New Issue
Block a user