aboutsummaryrefslogtreecommitdiff
path: root/test/dead_end.ml
blob: 9cce62d9d9538a0ff811ccde107f42601298dcfd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
module Dead_end = Qsp_syntax.Dead_end
module S = Qsp_syntax.S

let _position = (Lexing.dummy_pos, Lexing.dummy_pos)
let pp_pos = Qsp_syntax.Report.pp_pos

type pos = S.pos

let equal_pos : pos -> pos -> bool = fun _ _ -> true

type t = Qsp_syntax.Report.t = {
  level : Qsp_syntax.Report.level;
  loc : pos;
  message : string;
}
[@@deriving show, eq]

let report : Qsp_syntax.Report.t list Alcotest.testable =
  Alcotest.list @@ Alcotest.testable Qsp_syntax.Report.pp equal

let parse :
    string ->
    (Dead_end.Location.t * Qsp_syntax.Report.t list, Qsp_syntax.Report.t) result
    =
 fun content ->
  let lexing =
    Sedlexing.Latin1.from_string content |> Qparser.Lexbuf.from_lexbuf
  in
  Qparser.Analyzer.parse (module Dead_end) lexing

let get_report :
    (Dead_end.Location.t * Qsp_syntax.Report.t list, Qsp_syntax.Report.t) result ->
    Qsp_syntax.Report.t list = function
  | Ok (_, report) -> report
  | Error _ -> failwith "Error"

let _test_instruction : string -> Qsp_syntax.Report.t list -> unit =
 fun literal expected ->
  let _location = Printf.sprintf {|# Location
%s
------- |} literal in
  let actual = get_report @@ parse _location and msg = literal in

  Alcotest.(check' report ~msg ~expected ~actual)

(** This one is OK because act provide a solution in any case *)
let ok () =
  _test_instruction {|
if 0:
	act '': gt ''
	if 1:
		act '': gt ''
	end
end
  |}
    []

(** Ignore top level dead end*)
let toplevel () =
  _test_instruction {|
act 1:
  act '': gt ''
end

if 1: act '': gt ''

  |} []

let else_branch () =
  _test_instruction
    {|
if 0:
	if 1:
		act '': gt ''
	else
		act '': ''
	end
end
  |}
    [
      {
        level = Warn;
        loc = _position;
        message = "Possible dead end (unmatched path)";
      };
    ]

let elseif_branch () =
  _test_instruction
    {|
if 0:
	if 1:
		act '': ''
    elseif 0:
		act '': gt ''
	end
end
  |}
    [
      {
        level = Debug;
        loc = _position;
        message = "Possible dead end (no else fallback)";
      };
    ]

let missing_else () =
  _test_instruction {|
if 0:
	if 1: act '': gt ''
end
  |}
    [
      {
        level = Debug;
        loc = _position;
        message = "Possible dead end (no else fallback)";
      };
    ]

let nothing () = _test_instruction {|
if 0:
	if 1: 0
end
  |} []

let test =
  ( "Dead end",
    [
      Alcotest.test_case "No dead_end" `Quick ok;
      Alcotest.test_case "top level" `Quick toplevel;
      Alcotest.test_case "Else branch" `Quick else_branch;
      Alcotest.test_case "ElseIf branch" `Quick elseif_branch;
      Alcotest.test_case "Missing else" `Quick missing_else;
      Alcotest.test_case "nothing" `Quick nothing;
    ] )