Merge pull request #866 from Skgland/add_tests

Add tests for some recently closed Issues
This commit is contained in:
Mark Thom
2021-03-13 00:39:01 -07:00
committed by GitHub
15 changed files with 433 additions and 67 deletions

89
Cargo.lock generated
View File

@@ -9,6 +9,20 @@ dependencies = [
"nodrop", "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]] [[package]]
name = "autocfg" name = "autocfg"
version = "0.1.7" version = "0.1.7"
@@ -87,6 +101,17 @@ dependencies = [
"byte-tools", "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]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.6.0" version = "3.6.0"
@@ -206,6 +231,12 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "difference"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.8.1" version = "0.8.1"
@@ -242,6 +273,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc9f8914dcb99891bdfee82536bbff8d9aa612b0dbe83872afbc66902bdec0b9" checksum = "bc9f8914dcb99891bdfee82536bbff8d9aa612b0dbe83872afbc66902bdec0b9"
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]] [[package]]
name = "downcast" name = "downcast"
version = "0.10.0" version = "0.10.0"
@@ -851,6 +888,32 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" 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]] [[package]]
name = "proc-macro-hack" name = "proc-macro-hack"
version = "0.5.19" version = "0.5.19"
@@ -1091,6 +1154,15 @@ version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d813022b2e00774a48eaf43caaa3c20b45f040ba8cbf398e2e8911a06668dbe6" 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]] [[package]]
name = "remove_dir_all" name = "remove_dir_all"
version = "0.5.3" version = "0.5.3"
@@ -1202,6 +1274,7 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
name = "scryer-prolog" name = "scryer-prolog"
version = "0.8.128" version = "0.8.128"
dependencies = [ dependencies = [
"assert_cmd",
"base64", "base64",
"blake2", "blake2",
"chrono", "chrono",
@@ -1220,6 +1293,7 @@ dependencies = [
"num-rug-adapter", "num-rug-adapter",
"openssl", "openssl",
"ordered-float", "ordered-float",
"predicates-core",
"prolog_parser", "prolog_parser",
"ref_thread_local", "ref_thread_local",
"ring", "ring",
@@ -1492,6 +1566,12 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "treeline"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41"
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.12.0" version = "1.12.0"
@@ -1571,6 +1651,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 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]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.2+wasi-snapshot-preview1" version = "0.10.2+wasi-snapshot-preview1"

View File

@@ -52,3 +52,7 @@ roxmltree = "0.11.0"
base64 = "0.12.3" base64 = "0.12.3"
sodiumoxide = "0.2.6" sodiumoxide = "0.2.6"
slice-deque = "0.3.0" slice-deque = "0.3.0"
[dev-dependencies]
assert_cmd = "1.0.3"
predicates-core = "1.0.2"

View File

@@ -365,7 +365,17 @@ impl Stream {
} }
pub fn bytes(&self) -> Option<std::cell::Ref<Vec<u8>>> { 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| { let val = std::cell::Ref::map(self.stream_inst.0.borrow(), |inner_stream| {
&inner_stream.stream_inst &inner_stream.stream_inst
}); });

View File

@@ -0,0 +1,4 @@
% hello
% line!
a :- b(X).

View File

@@ -0,0 +1,3 @@
test :- write(world), nl.
:- initialization(write(hello)).

View File

@@ -0,0 +1 @@
:- initialization(call).

1
tests-pl/issue839-op3.pl Normal file
View File

@@ -0,0 +1 @@
:- op(900, fy, [$,@]).

View File

@@ -0,0 +1,3 @@
:- set_prolog_flag(occurs_check, true).
f(X, g(X)).

View File

@@ -0,0 +1 @@
:- initialization(throw(e)).

6
tests-pl/syntax_error.pl Normal file
View 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).

View File

@@ -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
View 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
View 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
View File

@@ -0,0 +1,4 @@
mod helper;
mod issues;
mod src_tests;

59
tests/scryer/src_tests.rs Normal file
View 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", "");
}