aboutsummaryrefslogtreecommitdiff
path: root/tests/analyser_dependency.ml
blob: dea77279057e27d24095daf2f6d4ccc7bfa476ee (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
open OUnit2
open StdLabels
module A = ImportAnalyser.Dependency
module Cont = ImportContainers
module Syntax = ImportConf.Syntax
module Expression = ImportExpression.T
module Table = ImportDataTypes.Table
open ConfLoader

let test_order =
  "Order" >:: fun _ ->
  let order = A.get_process_order conf |> List.map ~f:A.table in
  let expected_order =
    [ external_table_last; external_table_other; external_table_source ]
  in
  assert_equal ~cmp:(cmp_list cmp_source) ~printer:show_sources expected_order
    order

let test_columns =
  "Columns" >:: fun _ ->
  let expected_colums = Cont.IntSet.of_list [ 1; 2 ] in
  let columns =
    A.get_process_order conf
    |> List.find ~f:(fun v -> A.table v = external_table_source)
    |> A.columns
  in

  assert_equal
    ~cmp:(fun a b -> 0 = Cont.IntSet.compare a b)
    ~printer:Cont.show_intSet expected_colums columns

let test_keys =
  "Keys" >:: fun _ ->
  (* We should have one key in the table other, because it is referenced as a
     source in last file *)
  let expected_keys =
    A.
      [
        {
          name = "other";
          expression = Expression.Path 3;
          columns = lazy (Cont.IntSet.singleton 3);
        };
      ]
  in

  let keys =
    A.get_process_order conf
    |> List.find ~f:(fun v -> A.table v = external_table_other)
    |> A.keys
  in

  assert_equal ~cmp:(cmp_list key_cmp) ~printer:keys_printer expected_keys keys

let test_keys_missing =
  "Keys missing" >:: fun _ ->
  (* We have no key in last_file because the key is declared as missing *)
  let expected_keys =
    A.
      [
        {
          name = "last_file";
          expression = Expression.Path 3;
          columns = lazy (Cont.IntSet.singleton 3);
        };
      ]
  in

  let keys =
    A.get_process_order conf
    |> List.find ~f:(fun v -> A.table v = external_table_last)
    |> A.keys
  in

  assert_equal ~cmp:(cmp_list key_cmp) ~printer:keys_printer expected_keys keys

let test_unknow_source =
  "Unknown source" >:: fun _ ->
  let conf = { conf with externals = [] } in
  assert_raises (ImportErrors.Unknown_source "last_file") (fun () ->
      A.get_process_order conf)

let test_unordered =
  "Unorderd references" >:: fun _ ->
  (* Externals not described in the right order shall not raise any
     error. *)
  let conf =
    load
      {|version = 1
[source]
  file = "source.xlsx"
  name = "source"

[externals.last_file]
  intern_key = ":other.A"
  file = "last.xlsx"
  extern_key = ":C"
  allow_missing = true 

[externals.other]
  intern_key = ":A"
  file = "other.xlsx"
  extern_key = ":C"
  allow_missing = false

[sheet]
  columns = []|}
  in
  assert_raises (ImportErrors.Unknown_source "other") (fun () ->
      A.get_process_order conf)

let test_circular =
  "Unlinked reference" >:: fun _ ->
  (* A reference to itself should be understood *)
  let conf =
    load
      {|version = 1
[source]
  file = "source.xlsx"
  name = "source"

[externals.circular]
  intern_key = ":circular.A"
  file = "last.xlsx"
  extern_key = ":A"
  allow_missing = true 

[sheet]
  columns = []|}
  in

  let elements = A.get_process_order conf in
  assert_equal ~printer:string_of_int 1 (List.length elements)

let test_unlinked =
  "Circular reference" >:: fun _ ->
  (* An element linked to anything (except itself) should be ignored *)
  let conf =
    Syntax.
      {
        version = 1;
        source = external_table_source;
        externals =
          [
            {
              intern_key = Path { alias = Some "circular2"; column = 1 };
              target = { file = "other.xlsx"; tab = 1; name = "circular" };
              extern_key = Path 3;
              allow_missing = true;
              match_rule = None;
            };
            {
              intern_key = Path { alias = Some "circular"; column = 1 };
              target = { file = "other2.xlsx"; tab = 1; name = "circular2" };
              extern_key = Path 3;
              allow_missing = true;
              match_rule = None;
            };
          ];
        columns = [];
        filters = [];
        sort = [];
        uniq = [];
      }
  in
  assert_raises (ImportErrors.Unknown_source "circular2") (fun () ->
      A.get_process_order conf |> List.map ~f:A.table)

let conf_with_unlinked =
  Syntax.
    {
      version = 1;
      source = external_table_source;
      externals =
        [
          {
            intern_key = Path { alias = None; column = 1 };
            target = { file = "other.xlsx"; tab = 1; name = "other" };
            extern_key = Path 3;
            allow_missing = false;
            match_rule = None;
          };
        ];
      columns =
        [
          Concat [ Path { alias = None; column = 1 }; Literal "_"; Empty ];
          Path { alias = None; column = 2 };
        ];
      filters = [];
      sort = [];
      uniq = [];
    }

(** A table referenced only in a filter list shall be loaded correctly *)
let test_order_filter =
  "Order filter" >:: fun _ ->
  let order =
    {
      conf_with_unlinked with
      filters = [ Path { alias = Some "other"; column = 5 } ];
    }
    |> A.get_process_order |> List.map ~f:A.table
  in
  let expected_order = [ external_table_other; external_table_source ] in
  assert_equal ~printer:show_sources expected_order order

(** A table referenced only in the order list shall be loaded correctly *)
let test_order_sort =
  "Order sort" >:: fun _ ->
  let order =
    {
      conf_with_unlinked with
      sort = [ Path { alias = Some "other"; column = 5 } ];
    }
    |> A.get_process_order |> List.map ~f:A.table
  in
  let expected_order = [ external_table_other; external_table_source ] in
  assert_equal ~printer:show_sources expected_order order

(** A table referenced only in the uniq list shall be loaded correctly *)
let test_order_uniq =
  "Order uniq" >:: fun _ ->
  let order =
    {
      conf_with_unlinked with
      uniq = [ Path { alias = Some "other"; column = 5 } ];
    }
    |> A.get_process_order |> List.map ~f:A.table
  in
  let expected_order = [ external_table_other; external_table_source ] in
  assert_equal ~printer:show_sources expected_order order

let tests =
  "analyser_dependency"
  >::: [
         test_order;
         test_columns;
         test_keys;
         test_keys_missing;
         test_unknow_source;
         test_unordered;
         test_circular;
         test_unlinked;
         test_order_filter;
         test_order_sort;
         test_order_uniq;
       ]