aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/dup_cases.ml10
-rw-r--r--test/dynamics.ml93
-rw-r--r--test/get_type.ml68
-rw-r--r--test/literals.ml15
-rw-r--r--test/location.ml14
-rw-r--r--test/make_checkTest.ml91
-rw-r--r--test/qsp_parser_test.ml1
-rw-r--r--test/syntax.ml7
-rw-r--r--test/syntax_error.ml34
-rw-r--r--test/type_of.ml2
10 files changed, 252 insertions, 83 deletions
diff --git a/test/dup_cases.ml b/test/dup_cases.ml
index 8b9f846..76a1157 100644
--- a/test/dup_cases.ml
+++ b/test/dup_cases.ml
@@ -28,8 +28,7 @@ elseif rnd:
end
|} []
-(** The same test in two differents block shall be considered as a duplicate.
- *)
+(** The same test in two differents block shall be considered as a duplicate. *)
let ok_act () =
_test_instruction
{|
@@ -61,14 +60,13 @@ end
{
level = Warn;
loc = _position;
- message = "This case is duplicated line(s) 5";
+ message = "This case is duplicated line(s) 4";
};
]
let duplicate_root_test () =
_test_instruction
- {|
-if args[0] = 1:
+ {|if args[0] = 1:
0
end
if args[0] = 1:
@@ -81,7 +79,7 @@ end
{
level = Warn;
loc = _position;
- message = "This case is duplicated line(s) 6";
+ message = "This case is duplicated line(s) 4";
};
]
diff --git a/test/dynamics.ml b/test/dynamics.ml
new file mode 100644
index 0000000..ad980f4
--- /dev/null
+++ b/test/dynamics.ml
@@ -0,0 +1,93 @@
+module Check = Make_checkTest.M (Qsp_checks.Dynamics)
+module S = Qsp_syntax.S
+
+let position = (Lexing.dummy_pos, Lexing.dummy_pos)
+
+module Testable = struct
+ type pos = S.pos
+
+ let pp_pos = Qsp_syntax.Report.pp_pos
+ let equal_pos : pos -> pos -> bool = fun _ _ -> true
+
+ type t = Qsp_checks.Dynamics.text = { content : string; position : pos }
+ [@@deriving show, eq]
+
+ let v = Alcotest.list (Alcotest.testable pp equal)
+end
+
+let _parse : string -> Testable.t list -> unit =
+ fun literal expected ->
+ let context = Qsp_checks.Dynamics.initialize () in
+ (* The result of the parsing can be discarded, the usefull information is in
+ the context *)
+ let result =
+ Check._parse ~context Qparser.Analyzer.Dynamic (literal ^ "\n")
+ in
+ match result with
+ | Ok _ ->
+ let actual : Qsp_checks.Dynamics.text List.t =
+ Qsp_checks.Dynamics.dynamics_string context |> List.of_seq
+ in
+ let msg = literal in
+ Alcotest.(check' Testable.v ~msg ~expected ~actual)
+ | Error _ -> raise (Failure "Syntax error")
+
+let test_direct () =
+ _parse "dynamic '$a = 1'"
+ [ { Qsp_checks.Dynamics.content = "$a = 1"; position } ]
+
+let test_indirect () =
+ _parse "$test = '$a = 1' & dynamic $test"
+ [ { Qsp_checks.Dynamics.content = "$a = 1"; position } ]
+
+let test_indirect_array () =
+ _parse "$test[0] = '$a = 1' & dynamic $test[0]"
+ [ { Qsp_checks.Dynamics.content = "$a = 1"; position } ];
+
+ _parse "$test['a'] = '$a = 1' & dynamic $test['a']"
+ [ { Qsp_checks.Dynamics.content = "$a = 1"; position } ];
+
+ _parse "$test[0] = '$a = 1' & dynamic $test[1]" []
+
+(** If a variable is identified as dynamic, check all the differents values this
+ variable can have *)
+let test_reassignation () =
+ _parse
+ {|$test = '$a = 1'
+ $test = '$a = 2'
+ dynamic $test|}
+ [
+ { Qsp_checks.Dynamics.content = "$a = 1"; position };
+ { Qsp_checks.Dynamics.content = "$a = 2"; position };
+ ]
+
+(** If the variable contains a dynamic assignation, blacklist it from being
+ checkable*)
+let test_blacklist () =
+ _parse {|$test = '$a = 1'
+ $test = $b + ''
+ dynamic $test|} []
+
+(** Ignore string template because this can be anything *)
+let test_template_str () = _parse "dynamic '$a = <<$other>>'" []
+
+let test_template_str2 () =
+ _parse {|dynamic '$a = <<"other">>'|}
+ [ { Qsp_checks.Dynamics.content = "$a = other"; position } ]
+
+let test_template_int () =
+ _parse "dynamic '$a = <<other>>'"
+ [ { Qsp_checks.Dynamics.content = "$a = 0"; position } ]
+
+let test =
+ ( "Dynamic evaluation checker",
+ [
+ Alcotest.test_case "direct" `Quick test_direct;
+ Alcotest.test_case "indirect" `Quick test_indirect;
+ Alcotest.test_case "indirect array" `Quick test_indirect_array;
+ Alcotest.test_case "template" `Quick test_template_str;
+ Alcotest.test_case "template" `Quick test_template_str2;
+ Alcotest.test_case "template int" `Quick test_template_int;
+ Alcotest.test_case "reassignation" `Quick test_reassignation;
+ Alcotest.test_case "blacklist" `Quick test_blacklist;
+ ] )
diff --git a/test/get_type.ml b/test/get_type.ml
index 55f087e..56b4689 100644
--- a/test/get_type.ml
+++ b/test/get_type.ml
@@ -3,79 +3,84 @@ module T = Qsp_syntax.T
let _position = (Lexing.dummy_pos, Lexing.dummy_pos)
-let type_of : Get_type.t Alcotest.testable =
- Alcotest.testable Get_type.pp Get_type.equal
+let type_of : Get_type.Expression.t Alcotest.testable =
+ Alcotest.testable Get_type.Expression.pp Get_type.Expression.equal
+
+let ctx = Qsp_syntax.S.{ f = (fun _ -> None) }
let add_number () =
let actual =
- Get_type.boperator _position T.Plus
- (Get_type.integer _position "0")
- (Get_type.integer _position "1")
+ Get_type.Expression.boperator ~ctx _position T.Plus
+ (Get_type.Expression.integer ~ctx _position "0")
+ (Get_type.Expression.integer ~ctx _position "1")
in
- let expected = Get_type.(Raw Integer) in
+ let expected = Get_type.Expression.(Raw Integer) in
let msg = "Adding integer" in
Alcotest.(check' type_of ~msg ~expected ~actual)
let add_literal_number () =
let actual =
- Get_type.boperator _position T.Plus
- (Get_type.literal _position [ T.Text "2" ])
- (Get_type.integer _position "1")
+ Get_type.Expression.boperator ~ctx _position T.Plus
+ (Get_type.Expression.literal ~ctx _position [ T.Text "2" ])
+ (Get_type.Expression.integer ~ctx _position "1")
in
- let expected = Get_type.(Raw Integer) in
+ let expected = Get_type.Expression.(Raw Integer) in
let msg = "A string containing integer is considered as integer" in
Alcotest.(check' type_of ~msg ~expected ~actual)
let concat_text () =
let actual =
- Get_type.boperator _position T.Plus
- (Get_type.literal _position [ T.Text "a" ])
- (Get_type.integer _position "1")
+ Get_type.Expression.boperator ~ctx _position T.Plus
+ (Get_type.Expression.literal ~ctx _position [ T.Text "a" ])
+ (Get_type.Expression.integer ~ctx _position "1")
in
- let expected = Get_type.(Raw String) in
+ let expected = Get_type.Expression.(Raw String) in
let msg = "Concatenate" in
Alcotest.(check' type_of ~msg ~expected ~actual)
let literal_1 () =
let actual =
- Get_type.literal _position [ T.Expression (Get_type.Raw Integer) ]
- and expected = Get_type.(Raw NumericString) in
+ Get_type.Expression.literal ~ctx _position
+ [ T.Expression (Get_type.Expression.Raw Integer) ]
+ and expected = Get_type.Expression.(Raw NumericString) in
let msg = "" in
Alcotest.(check' type_of ~msg ~expected ~actual)
let literal_2 () =
let actual =
- Get_type.literal _position
- Get_type.[ T.Text "1"; T.Expression (Raw Integer) ]
- and expected = Get_type.(Raw NumericString) in
+ Get_type.Expression.literal ~ctx _position
+ Get_type.Expression.[ T.Text "1"; T.Expression (Raw Integer) ]
+ and expected = Get_type.Expression.(Raw NumericString) in
let msg = "" in
Alcotest.(check' type_of ~msg ~expected ~actual)
let literal_3 () =
let actual =
- Get_type.literal _position
- Get_type.[ T.Text "b"; T.Expression (Raw Integer) ]
- and expected = Get_type.(Raw String) in
+ Get_type.Expression.literal ~ctx _position
+ Get_type.Expression.[ T.Text "b"; T.Expression (Raw Integer) ]
+ and expected = Get_type.Expression.(Raw String) in
let msg = "" in
Alcotest.(check' type_of ~msg ~expected ~actual)
let literal_4 () =
let actual =
- Get_type.literal _position [ T.Expression (Get_type.Variable Integer) ]
- and expected = Get_type.(Variable NumericString) in
+ Get_type.Expression.literal ~ctx _position
+ Get_type.Expression.[ T.Expression (Variable Integer) ]
+ and expected = Get_type.Expression.(Variable NumericString) in
let msg = "" in
Alcotest.(check' type_of ~msg ~expected ~actual)
let min () =
- let actual = Get_type.function_ _position T.Min [] in
- let expected = Get_type.(Raw Bool) in
+ let actual = Get_type.Expression.function_ ~ctx _position T.Min [] in
+ let expected = Get_type.Expression.(Raw Bool) in
let msg = "The function min without argument return a default value" in
Alcotest.(check' type_of ~msg ~expected ~actual);
let actual =
- Get_type.function_ _position T.Min [ Get_type.literal _position [] ]
+ Get_type.Expression.function_ ~ctx _position T.Min
+ [ Get_type.Expression.literal ~ctx _position [] ]
in
- let expected = Get_type.(Variable NumericString) in
+ let expected = Get_type.Expression.(Variable NumericString) in
let msg =
"The function min with a literal will take the literal as the name of an \
array"
@@ -83,10 +88,11 @@ let min () =
Alcotest.(check' type_of ~msg ~expected ~actual);
let actual =
- Get_type.function_ _position T.Min
- [ Get_type.integer _position ""; Get_type.integer _position "" ]
+ Get_type.Expression.function_ ~ctx _position T.Min
+ Get_type.Expression.
+ [ integer ~ctx _position ""; integer ~ctx _position "" ]
in
- let expected = Get_type.(Raw Integer) in
+ let expected = Get_type.Expression.(Raw Integer) in
let msg = "With two or more arguments, return the type of the first one" in
Alcotest.(check' type_of ~msg ~expected ~actual)
diff --git a/test/literals.ml b/test/literals.ml
index f98fa8f..2685538 100644
--- a/test/literals.ml
+++ b/test/literals.ml
@@ -107,6 +107,20 @@ let multiple_expression () =
] ));
]
+let int_expression () =
+ _test_instruction {|"<<expr2>>"|}
+ [
+ Tree.Ast.Expression
+ (Tree.Ast.Literal
+ ( _position,
+ [
+ T.Expression
+ (Tree.Ast.Ident
+ { Tree.Ast.pos = _position; name = "EXPR2"; index = None });
+ T.Text "";
+ ] ));
+ ]
+
let test =
( "Literals",
[
@@ -127,4 +141,5 @@ let test =
Alcotest.test_case "elements_sequence" `Quick elements_sequence;
Alcotest.test_case "expression" `Quick expression;
Alcotest.test_case "multiple_expression" `Quick multiple_expression;
+ Alcotest.test_case "multiple_expression" `Quick int_expression;
] )
diff --git a/test/location.ml b/test/location.ml
index a1939f4..decf270 100644
--- a/test/location.ml
+++ b/test/location.ml
@@ -5,7 +5,7 @@ let _position = (Lexing.dummy_pos, Lexing.dummy_pos)
let error_message =
[
( "Location",
- Check.
+ Make_checkTest.
{
level = Error;
loc = _position;
@@ -18,11 +18,21 @@ let ok_upper () = Check.global_check "gt 'LOCATION'" []
let missing_gt () = Check.global_check "gt 'unknown_place'" error_message
let missing_gs () = Check.global_check "gs 'unknown_place'" error_message
+let act_missing_gs () =
+ Check.global_check {|
+act "test": gs 'unknown_place'|} error_message
+
+let if_missing_gs () =
+ Check.global_check {|
+ if 0: gs 'unknown_place'|} error_message
+
let test =
- ( "Locations",
+ ( __FILE__,
[
Alcotest.test_case "Ok" `Quick ok;
Alcotest.test_case "Ok upper" `Quick ok_upper;
Alcotest.test_case "Missing GT" `Quick missing_gt;
Alcotest.test_case "Missing GS" `Quick missing_gs;
+ Alcotest.test_case "Missing GS in block" `Quick act_missing_gs;
+ Alcotest.test_case "Missing GS in block'" `Quick if_missing_gs;
] )
diff --git a/test/make_checkTest.ml b/test/make_checkTest.ml
index d3ad358..7ffd17c 100644
--- a/test/make_checkTest.ml
+++ b/test/make_checkTest.ml
@@ -1,69 +1,92 @@
-(** Build a parser for a specific check module *)
-module M (Check : Qsp_syntax.S.Analyzer) = struct
- module S = Qsp_syntax.S
+module S = Qsp_syntax.S
+
+type pos = S.pos
- let pp_pos = Qsp_syntax.Report.pp_pos
+let pp_pos = Qsp_syntax.Report.pp_pos
+let equal_pos : pos -> pos -> bool = fun _ _ -> true
- type pos = S.pos
+type t = Qsp_syntax.Report.t = {
+ level : Qsp_syntax.Report.level;
+ loc : pos;
+ message : string;
+}
+[@@deriving show, eq]
- let equal_pos : pos -> pos -> bool = fun _ _ -> true
+let report : t list Alcotest.testable =
+ Alcotest.list @@ Alcotest.testable Qsp_syntax.Report.pp equal
- type t = Qsp_syntax.Report.t = {
- level : Qsp_syntax.Report.level;
- loc : pos;
- message : string;
- }
- [@@deriving show, eq]
+let report_global : (string * t) list Alcotest.testable =
+ Alcotest.list
+ @@ Alcotest.pair Alcotest.string
+ (Alcotest.testable Qsp_syntax.Report.pp equal)
- let report : t list Alcotest.testable =
- Alcotest.list @@ Alcotest.testable Qsp_syntax.Report.pp equal
+(** Build a parser for a specific check module *)
+module M
+ (Checkable : Qsp_syntax.Analyzer.T with type ex = Qsp_syntax.Identifier.t) =
+struct
+ let context_id = Type.Id.make ()
- let report_global : (string * t) list Alcotest.testable =
- Alcotest.list
- @@ Alcotest.pair Alcotest.string
- (Alcotest.testable Qsp_syntax.Report.pp equal)
+ (* Build the test module with a single test inside. *)
+ module Check = Qsp_checks.Check.Make (struct
+ let t = [| Qsp_syntax.Identifier.build ~context_id (module Checkable) |]
+ end)
- let parse :
- ?context:Check.context ->
+ let _parse :
+ ?context:Checkable.context ->
+ Qparser.Analyzer.lexer ->
string ->
(Check.Location.t Qparser.Analyzer.result, t) result =
- fun ?context content ->
+ fun ?context lexer content ->
let lexing =
Sedlexing.Latin1.from_string content |> Qparser.Lexbuf.from_lexbuf
in
- let context = Option.value context ~default:(Check.initialize ()) in
- Qparser.Analyzer.parse (module Check) lexing context
+ (* Initialize the context *inside* the Check module. This works by
+ editing the context we created.
+
+ We have the context id (created at the begining of the module), which is
+ required to get the value. *)
+ let context =
+ match context with
+ | None -> Check.initialize ()
+ | Some c -> (
+ let init = Check.initialize () in
+ match Qsp_checks.Check.set context_id init.(0) c with
+ | None -> raise Not_found
+ | Some v ->
+ init.(0) <- v;
+ init)
+ in
+ Qparser.Analyzer.parse (module Check) lexer lexing context
let get_report :
(Check.Location.t Qparser.Analyzer.result, Qsp_syntax.Report.t) result ->
Qsp_syntax.Report.t list = function
| Ok v -> v.report
- | Error _ -> failwith "Error"
+ | Error msg -> failwith msg.message
let _test_instruction : string -> t list -> unit =
fun literal expected ->
- let _location = Printf.sprintf {|# Location
-%s
-------- |} literal in
- let actual = get_report @@ parse _location and msg = literal in
+ let actual = get_report @@ _parse Qparser.Analyzer.Dynamic literal
+ and msg = literal in
Alcotest.(check' report ~msg ~expected ~actual)
- (** Run a test over the whole file.
- The parsing of the content shall not report any error.
- *)
+ (** Run a test over the whole file. The parsing of the content shall not
+ report any error. *)
let global_check : string -> (string * t) list -> unit =
fun literal expected ->
let _location = Printf.sprintf {|# Location
%s
------- |} literal in
- let context = Check.initialize () in
- let actual = get_report @@ parse ~context _location in
+ let context = Checkable.initialize () in
+ let actual =
+ get_report @@ _parse ~context Qparser.Analyzer.Location _location
+ in
let () =
Alcotest.(
check' report ~msg:"Error reported during parsing" ~expected:[] ~actual)
in
let msg = literal in
- let actual = Check.finalize context in
+ let actual = Checkable.finalize context in
Alcotest.(check' report_global ~msg ~expected ~actual)
end
diff --git a/test/qsp_parser_test.ml b/test/qsp_parser_test.ml
index 43f9cb3..4ae5a4c 100644
--- a/test/qsp_parser_test.ml
+++ b/test/qsp_parser_test.ml
@@ -11,4 +11,5 @@ let () =
Nested_string.test;
Location.test;
Dup_cases.test;
+ Dynamics.test;
]
diff --git a/test/syntax.ml b/test/syntax.ml
index db449b1..ce3e89e 100644
--- a/test/syntax.ml
+++ b/test/syntax.ml
@@ -4,7 +4,8 @@ module Check = Qsp_checks.Check
module S = Qsp_syntax.S
module T = Qsp_syntax.T
-let location_id, e1 = Qsp_syntax.Catalog.build (module Tree)
+let location_id = Type.Id.make ()
+let e1 = Qsp_syntax.Identifier.build ~location_id (module Tree)
module Parser = Check.Make (struct
let t = [| e1 |]
@@ -28,7 +29,9 @@ let parse : string -> (S.pos location, Qsp_syntax.Report.t) result =
Sedlexing.Latin1.from_string content |> Qparser.Lexbuf.from_lexbuf
in
let context = Parser.initialize () in
- Qparser.Analyzer.parse (module Parser) lexing context
+ Qparser.Analyzer.parse
+ (module Parser)
+ Qparser.Analyzer.Location lexing context
|> Result.map (fun v ->
(* Uncatched excteptions here, but we are in the tests…
If it’s fail here I have an error in the code. *)
diff --git a/test/syntax_error.ml b/test/syntax_error.ml
index b92cf28..9d51cf3 100644
--- a/test/syntax_error.ml
+++ b/test/syntax_error.ml
@@ -57,14 +57,15 @@ let elseif_no_column () =
}
let unclosed_paren () =
- _test_instruction
- {|(1
- |}
+ let expected =
{
level = Error;
loc = _position;
message = "Unexpected '('. Did you forgot a function before ?";
}
+ in
+ _test_instruction "(1" expected;
+ _test_instruction "'<<(1>>'" expected
let act_no_column () =
_test_instruction
@@ -113,8 +114,12 @@ let missing_operand () =
()
let unknow_function () =
- _test_instruction "a = ran(1, 2)"
+ let expected =
{ level = Error; loc = _position; message = "Unexpected expression here." }
+ in
+ _test_instruction "ran(1, 2)" expected;
+ _test_instruction "'<<ran(1, 2)>>'" expected;
+ _test_instruction "rand(1,2))" expected
let inline_elif () =
_test_instruction {|
@@ -194,9 +199,8 @@ let missing_comparable () =
_test_instruction "1 <= or 0" result;
_test_instruction "1 = or 0" result
-(** This code looks like a new location, but is actualy invalid.
- The application should report the old location.
- *)
+(** This code looks like a new location, but is actualy invalid. The application
+ should report the old location. *)
let location_change () =
let result =
{
@@ -272,6 +276,20 @@ let nested_string_mess () =
|}
{ level = Error; loc = _position; message = "Unclosed string" }
+let unexpected_bracket () =
+ let expected =
+ { level = Error; loc = _position; message = "Unbalanced paren" }
+ in
+ _test_instruction {|a[]]|} expected;
+ _test_instruction {|"<<a[]]>>"|} expected;
+ _test_instruction "'<<rand(1,2))>>'" expected
+
+let missing_operator () =
+ _test_instruction {|
+'' + $func('f', '') ''
+|}
+ { level = Error; loc = _position; message = "Missing operator before text" }
+
let test =
( "Syntax Errors",
[
@@ -295,4 +313,6 @@ let test =
Alcotest.test_case "act: else" `Quick unclosed_act;
Alcotest.test_case "+ =" `Quick unknown_operator;
Alcotest.test_case "'<<''>>'" `Quick nested_string_mess;
+ Alcotest.test_case "a[]]" `Quick unexpected_bracket;
+ Alcotest.test_case "Missing +" `Quick missing_operator;
] )
diff --git a/test/type_of.ml b/test/type_of.ml
index e816bc7..1b84faa 100644
--- a/test/type_of.ml
+++ b/test/type_of.ml
@@ -78,7 +78,7 @@ let concat_text () = _test_instruction {|$a = 'A' + 1|} []
let increment_string () = _test_instruction {|$a += 1|} (message' Error)
let test =
- ( "Typechecking",
+ ( __FILE__,
[
Alcotest.test_case "Assign str to int" `Quick type_mismatch;
Alcotest.test_case "$str = int" `Quick assign_int_str;