ovsdb: Add support for referential integrity in the database itself.
[cascardo/ovs.git] / tests / ovsdb-execution.at
1 AT_BANNER([OVSDB -- execution])
2
3 m4_define([ORDINAL_SCHEMA],
4   [[{"name": "mydb",
5      "tables": {
6        "ordinals": {
7          "columns": {
8            "number": {"type": "integer"},
9            "name": {"type": "string"}}}}}]])
10
11 m4_define([CONSTRAINT_SCHEMA],
12   [[{"name": "constraints",
13      "tables": {
14        "a": {
15          "columns": {
16            "a": {"type": "integer"},
17            "a2a": {"type": {"key": {"type": "uuid", "refTable": "a"},
18                             "min": 0, "max": "unlimited"}},
19            "a2b": {"type": {"key": {"type": "uuid", "refTable": "b"},
20                             "min": 0, "max": "unlimited"}}}},
21        "b": {
22          "columns": {
23            "b": {"type": "integer"},
24            "b2a": {"type": {"key": {"type": "uuid", "refTable": "a"},
25                             "min": 0, "max": "unlimited"}},
26            "b2b": {"type": {"key": {"type": "uuid", "refTable": "b"},
27                             "min": 0, "max": "unlimited"}}}},
28        "constrained": {
29          "columns": {
30            "positive": {"type": {"key": {"type": "integer",
31                                          "minInteger": 1}}}}}}}]])
32
33 # OVSDB_CHECK_EXECUTION(TITLE, SCHEMA, TRANSACTIONS, OUTPUT, [KEYWORDS])
34 #
35 # Runs "test-ovsdb execute" with the given SCHEMA and each of the
36 # TRANSACTIONS (which should be a quoted list of quoted strings).
37 #
38 # Checks that the overall output is OUTPUT, but UUIDs in the output
39 # are replaced by markers of the form <N> where N is a number.  The
40 # first unique UUID is replaced by <0>, the next by <1>, and so on.
41 # If a given UUID appears more than once it is always replaced by the
42 # same marker.
43 #
44 # TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS.
45 m4_define([OVSDB_CHECK_EXECUTION], 
46   [AT_SETUP([$1])
47    AT_KEYWORDS([ovsdb execute execution positive $5])
48    AT_CHECK([test-ovsdb execute '$2' m4_foreach([txn], [$3], [ 'txn'])],
49      [0], [stdout], [])
50    AT_CHECK([perl $srcdir/uuidfilt.pl stdout], [0], [$4])
51    AT_CLEANUP])
52
53 m4_define([EXECUTION_EXAMPLES], [
54 OVSDB_CHECK_EXECUTION([insert row, query table],
55   [ORDINAL_SCHEMA], 
56   [[[[{"op": "insert",
57        "table": "ordinals",
58        "row": {"number": 0, "name": "zero"}}]]],
59    [[[{"op": "select",
60        "table": "ordinals",
61        "where": []}]]]],
62   [[[{"uuid":["uuid","<0>"]}]
63 [{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<1>"],"name":"zero","number":0}]}]
64 ]])
65
66 OVSDB_CHECK_EXECUTION([insert rows, query by value],
67   [ORDINAL_SCHEMA],
68   [[[[{"op": "insert",
69        "table": "ordinals",
70        "row": {"number": 0, "name": "zero"}}]]],
71    [[[{"op": "insert",
72        "table": "ordinals",
73        "row": {"number": 1, "name": "one"}}]]],
74    [[[{"op": "select",
75        "table": "ordinals",
76        "where": [["name", "==", "zero"]]}]]],
77    [[[{"op": "select",
78        "table": "ordinals",
79        "where": [["name", "==", "one"]]}]]]],
80   [[[{"uuid":["uuid","<0>"]}]
81 [{"uuid":["uuid","<1>"]}]
82 [{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<2>"],"name":"zero","number":0}]}]
83 [{"rows":[{"_uuid":["uuid","<1>"],"_version":["uuid","<3>"],"name":"one","number":1}]}]
84 ]])
85
86 OVSDB_CHECK_EXECUTION([insert rows, query by named-uuid],
87   [ORDINAL_SCHEMA],
88   [[[[{"op": "insert",
89        "table": "ordinals",
90        "row": {"number": 0, "name": "zero"},
91        "uuid-name": "first"},
92       {"op": "insert",
93        "table": "ordinals",
94        "row": {"number": 1, "name": "one"},
95        "uuid-name": "second"},
96       {"op": "select",
97        "table": "ordinals",
98        "where": [["_uuid", "==", ["named-uuid", "first"]]]},
99       {"op": "select",
100        "table": "ordinals",
101        "where": [["_uuid", "==", ["named-uuid", "second"]]]}]]]],
102   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<2>"],"name":"zero","number":0}]},{"rows":[{"_uuid":["uuid","<1>"],"_version":["uuid","<3>"],"name":"one","number":1}]}]
103 ]])
104
105 OVSDB_CHECK_EXECUTION([insert rows, update rows by value],
106   [ORDINAL_SCHEMA],
107   [[[[{"op": "insert",
108        "table": "ordinals",
109        "row": {"number": 0, "name": "zero"},
110        "uuid-name": "first"}]]],
111    [[[{"op": "insert",
112        "table": "ordinals",
113        "row": {"number": 1, "name": "one"},
114        "uuid-name": "first"}]]],
115    [[[{"op": "update",
116        "table": "ordinals",
117        "where": [["name", "==", "zero"]],
118        "row": {"name": "nought"}}]]],
119    [[[{"op": "select",
120        "table": "ordinals",
121        "where": [],
122        "sort": ["number"]}]]]],
123   [[[{"uuid":["uuid","<0>"]}]
124 [{"uuid":["uuid","<1>"]}]
125 [{"count":1}]
126 [{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<2>"],"name":"nought","number":0},{"_uuid":["uuid","<1>"],"_version":["uuid","<3>"],"name":"one","number":1}]}]
127 ]])
128
129 OVSDB_CHECK_EXECUTION([insert rows, mutate rows],
130   [ORDINAL_SCHEMA],
131   [[[[{"op": "insert",
132        "table": "ordinals",
133        "row": {"number": 0, "name": "zero"},
134        "uuid-name": "first"}]]],
135    [[[{"op": "insert",
136        "table": "ordinals",
137        "row": {"number": 1, "name": "one"},
138        "uuid-name": "first"}]]],
139    [[[{"op": "mutate",
140        "table": "ordinals",
141        "where": [["name", "==", "zero"]],
142        "mutations": [["number", "+=", 2]]}]]],
143    [[[{"op": "select",
144        "table": "ordinals",
145        "where": [],
146        "sort": ["number"]}]]]],
147   [[[{"uuid":["uuid","<0>"]}]
148 [{"uuid":["uuid","<1>"]}]
149 [{"count":1}]
150 [{"rows":[{"_uuid":["uuid","<1>"],"_version":["uuid","<2>"],"name":"one","number":1},{"_uuid":["uuid","<0>"],"_version":["uuid","<3>"],"name":"zero","number":2}]}]
151 ]])
152
153 OVSDB_CHECK_EXECUTION([insert rows, delete by named-uuid],
154   [ORDINAL_SCHEMA],
155   [[[[{"op": "insert",
156        "table": "ordinals",
157        "row": {"number": 0, "name": "zero"},
158        "uuid-name": "first"},
159       {"op": "insert",
160        "table": "ordinals",
161        "row": {"number": 1, "name": "one"},
162        "uuid-name": "second"},
163       {"op": "delete",
164        "table": "ordinals",
165        "where": [["_uuid", "==", ["named-uuid", "first"]]]},
166       {"op": "select",
167        "table": "ordinals",
168        "where": [],
169        "columns": ["name","number"]}]]]],
170   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"count":1},{"rows":[{"name":"one","number":1}]}]
171 ]])
172
173 OVSDB_CHECK_EXECUTION([insert rows, delete rows by value],
174   [ORDINAL_SCHEMA],
175   [[[[{"op": "insert",
176        "table": "ordinals",
177        "row": {"number": 0, "name": "zero"},
178        "uuid-name": "first"}]]],
179    [[[{"op": "insert",
180        "table": "ordinals",
181        "row": {"number": 1, "name": "one"},
182        "uuid-name": "first"}]]],
183    [[[{"op": "delete",
184        "table": "ordinals",
185        "where": [["name", "==", "zero"]]}]]],
186    [[[{"op": "select",
187        "table": "ordinals",
188        "where": []}]]]],
189   [[[{"uuid":["uuid","<0>"]}]
190 [{"uuid":["uuid","<1>"]}]
191 [{"count":1}]
192 [{"rows":[{"_uuid":["uuid","<1>"],"_version":["uuid","<2>"],"name":"one","number":1}]}]
193 ]])
194
195 OVSDB_CHECK_EXECUTION([insert rows, delete by (non-matching) value],
196   [ORDINAL_SCHEMA],
197   [[[[{"op": "insert",
198        "table": "ordinals",
199        "row": {"number": 0, "name": "zero"},
200        "uuid-name": "first"}]]],
201    [[[{"op": "insert",
202        "table": "ordinals",
203        "row": {"number": 1, "name": "one"},
204        "uuid-name": "first"}]]],
205    [[[{"op": "delete",
206        "table": "ordinals",
207        "where": [["name", "==", "nought"]]}]]],
208    [[[{"op": "select",
209        "table": "ordinals",
210        "where": [],
211        "sort": ["number"]}]]]],
212   [[[{"uuid":["uuid","<0>"]}]
213 [{"uuid":["uuid","<1>"]}]
214 [{"count":0}]
215 [{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<2>"],"name":"zero","number":0},{"_uuid":["uuid","<1>"],"_version":["uuid","<3>"],"name":"one","number":1}]}]
216 ]])
217
218 OVSDB_CHECK_EXECUTION([insert rows, delete all],
219   [ORDINAL_SCHEMA],
220   [[[[{"op": "insert",
221        "table": "ordinals",
222        "row": {"number": 0, "name": "zero"},
223        "uuid-name": "first"},
224       {"op": "insert",
225        "table": "ordinals",
226        "row": {"number": 1, "name": "one"},
227        "uuid-name": "second"},
228       {"op": "delete",
229        "table": "ordinals",
230        "where": []},
231       {"op": "select",
232        "table": "ordinals",
233        "where": [],
234        "columns": ["name","number"]}]]]],
235   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"count":2},{"rows":[]}]
236 ]])
237
238 OVSDB_CHECK_EXECUTION([insert row, query table, commit],
239   [ORDINAL_SCHEMA],
240   [[[[{"op": "insert",
241        "table": "ordinals",
242        "row": {"number": 0, "name": "zero"}},
243       {"op": "select",
244        "table": "ordinals",
245        "where": []},
246       {"op": "commit",
247        "durable": false}]]]],
248   [[[{"uuid":["uuid","<0>"]},{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<1>"],"name":"zero","number":0}]},{}]
249 ]])
250
251 OVSDB_CHECK_EXECUTION([insert row, query table, commit durably],
252   [ORDINAL_SCHEMA],
253   [[[[{"op": "insert",
254        "table": "ordinals",
255        "row": {"number": 0, "name": "zero"}},
256       {"op": "select",
257        "table": "ordinals",
258        "where": []},
259       {"op": "commit",
260        "durable": true}]]]],
261   [[[{"uuid":["uuid","<0>"]},{"rows":[{"_uuid":["uuid","<0>"],"_version":["uuid","<1>"],"name":"zero","number":0}]},{}]
262 ]])
263
264 OVSDB_CHECK_EXECUTION([equality wait with correct rows],
265   [ORDINAL_SCHEMA],
266   [[[[{"op": "insert",
267        "table": "ordinals",
268        "row": {"number": 0, "name": "zero"}},
269       {"op": "insert",
270        "table": "ordinals",
271        "row": {"number": 1, "name": "one"}},
272       {"op": "wait",
273        "timeout": 0,
274        "table": "ordinals",
275        "where": [],
276        "columns": ["name", "number"],
277        "until": "==",
278        "rows": [{"name": "zero", "number": 0},
279                 {"name": "one", "number": 1}]}]]]],
280   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{}]
281 ]])
282
283 OVSDB_CHECK_EXECUTION([equality wait with extra row],
284   [ORDINAL_SCHEMA],
285   [[[[{"op": "insert",
286        "table": "ordinals",
287        "row": {"number": 0, "name": "zero"}},
288       {"op": "insert",
289        "table": "ordinals",
290        "row": {"number": 1, "name": "one"}},
291       {"op": "wait",
292        "timeout": 0,
293        "table": "ordinals",
294        "where": [],
295        "columns": ["name", "number"],
296        "until": "==",
297        "rows": [{"name": "zero", "number": 0},
298                 {"name": "one", "number": 1},
299                 {"name": "two", "number": 2}]}]]]],
300   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"details":"\"wait\" timed out","error":"timed out"}]
301 ]])
302
303 OVSDB_CHECK_EXECUTION([equality wait with missing row],
304   [ORDINAL_SCHEMA],
305   [[[[{"op": "insert",
306        "table": "ordinals",
307        "row": {"number": 0, "name": "zero"}},
308       {"op": "insert",
309        "table": "ordinals",
310        "row": {"number": 1, "name": "one"}},
311       {"op": "wait",
312        "timeout": 0,
313        "table": "ordinals",
314        "where": [],
315        "columns": ["name", "number"],
316        "until": "==",
317        "rows": [{"name": "one", "number": 1}]}]]]],
318   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"details":"\"wait\" timed out","error":"timed out"}]
319 ]])
320
321 OVSDB_CHECK_EXECUTION([inequality wait with correct rows],
322   [ORDINAL_SCHEMA],
323   [[[[{"op": "insert",
324        "table": "ordinals",
325        "row": {"number": 0, "name": "zero"}},
326       {"op": "insert",
327        "table": "ordinals",
328        "row": {"number": 1, "name": "one"}},
329       {"op": "wait",
330        "timeout": 0,
331        "table": "ordinals",
332        "where": [],
333        "columns": ["name", "number"],
334        "until": "!=",
335        "rows": [{"name": "zero", "number": 0},
336                 {"name": "one", "number": 1}]}]]]],
337   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"details":"\"wait\" timed out","error":"timed out"}]
338 ]])
339
340 OVSDB_CHECK_EXECUTION([inequality wait with extra row],
341   [ORDINAL_SCHEMA],
342   [[[[{"op": "insert",
343        "table": "ordinals",
344        "row": {"number": 0, "name": "zero"}},
345       {"op": "insert",
346        "table": "ordinals",
347        "row": {"number": 1, "name": "one"}},
348       {"op": "wait",
349        "timeout": 0,
350        "table": "ordinals",
351        "where": [],
352        "columns": ["name", "number"],
353        "until": "!=",
354        "rows": [{"name": "zero", "number": 0},
355                 {"name": "one", "number": 1},
356                 {"name": "two", "number": 2}]}]]]],
357   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{}]
358 ]])
359
360 OVSDB_CHECK_EXECUTION([inequality wait with missing row],
361   [ORDINAL_SCHEMA],
362   [[[[{"op": "insert",
363        "table": "ordinals",
364        "row": {"number": 0, "name": "zero"}},
365       {"op": "insert",
366        "table": "ordinals",
367        "row": {"number": 1, "name": "one"}},
368       {"op": "wait",
369        "timeout": 0,
370        "table": "ordinals",
371        "where": [],
372        "columns": ["name", "number"],
373        "until": "!=",
374        "rows": [{"name": "one", "number": 1}]}]]]],
375   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{}]
376 ]])
377
378 OVSDB_CHECK_EXECUTION([insert and update constraints],
379   [CONSTRAINT_SCHEMA],
380   [[[[{"op": "insert",
381        "table": "constrained",
382        "row": {}}]]],
383    [[[{"op": "insert",
384        "table": "constrained",
385        "row": {"positive": -1}}]]],
386    [[[{"op": "update",
387        "table": "constrained",
388        "where": [],
389        "row": {"positive": -2}}]]]],
390   [[[{"details":"0 is less than minimum allowed value 1","error":"constraint violation"}]
391 [{"details":"-1 is less than minimum allowed value 1","error":"constraint violation"}]
392 [{"details":"-2 is less than minimum allowed value 1","error":"constraint violation"}]
393 ]])
394
395 OVSDB_CHECK_EXECUTION([referential integrity -- simple],
396   [CONSTRAINT_SCHEMA],
397   [[[[{"op": "insert",
398        "table": "b",
399        "row": {"b": 1},
400        "uuid-name": "brow"},
401       {"op": "insert",
402        "table": "a",
403        "row": {"a": 0,
404                "a2b": ["set", [["named-uuid", "brow"]]]}},
405       {"op": "insert",
406        "table": "a",
407        "row": {"a": 1,
408                "a2b": ["set", [["named-uuid", "brow"]]]}},
409       {"op": "insert",
410        "table": "a",
411        "row": {"a": 2,
412                "a2b": ["set", [["named-uuid", "brow"]]]}}]]],
413    [[[{"op": "delete",
414        "table": "b",
415        "where": []}]]],
416    [[[{"op": "delete",
417        "table": "a",
418        "where": [["a", "==", 0]]}]]],
419    [[[{"op": "delete",
420        "table": "b",
421        "where": []}]]],
422    [[[{"op": "delete",
423        "table": "a",
424        "where": [["a", "==", 1]]}]]],
425    [[[{"op": "delete",
426        "table": "b",
427        "where": []}]]],
428    [[[{"op": "delete",
429        "table": "a",
430        "where": [["a", "==", 2]]}]]],
431    [[[{"op": "delete",
432        "table": "b",
433        "where": []}]]]],
434   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<2>"]},{"uuid":["uuid","<3>"]}]
435 [{"count":1},{"details":"cannot delete b row <0> because of 3 remaining reference(s)","error":"referential integrity violation"}]
436 [{"count":1}]
437 [{"count":1},{"details":"cannot delete b row <0> because of 2 remaining reference(s)","error":"referential integrity violation"}]
438 [{"count":1}]
439 [{"count":1},{"details":"cannot delete b row <0> because of 1 remaining reference(s)","error":"referential integrity violation"}]
440 [{"count":1}]
441 [{"count":1}]
442 ]])
443
444 OVSDB_CHECK_EXECUTION([referential integrity -- mutual references],
445   [CONSTRAINT_SCHEMA],
446   [[[[{"op": "declare",
447        "uuid-name": "row1"},
448       {"op": "declare",
449        "uuid-name": "row2"},
450       {"op": "insert",
451        "table": "a",
452        "row": {"a": 0,
453                "a2b": ["set", [["named-uuid", "row2"]]],
454                "a2a": ["set", [["named-uuid", "row1"]]]},
455        "uuid-name": "row1"},
456       {"op": "insert",
457        "table": "b",
458        "row": {"b": 1,
459                "b2b": ["set", [["named-uuid", "row2"]]],
460                "b2a": ["set", [["named-uuid", "row1"]]]},
461        "uuid-name": "row2"}]]],
462    [[[{"op": "insert",
463        "table": "a",
464        "row": {"a2b": ["set", [["uuid", "b516b960-5b19-4fc2-bb82-fe1cbd6d0241"]]]}}]]],
465    [[[{"op": "delete",
466        "table": "a",
467        "where": [["a", "==", 0]]}]]],
468    [[[{"op": "delete",
469        "table": "b",
470        "where": [["b", "==", 1]]}]]],
471    dnl Try the deletions again to make sure that the refcounts got rolled back.
472    [[[{"op": "delete",
473        "table": "a",
474        "where": [["a", "==", 0]]}]]],
475    [[[{"op": "delete",
476        "table": "b",
477        "where": [["b", "==", 1]]}]]],
478    [[[{"op": "delete",
479        "table": "a",
480        "where": [["a", "==", 0]]},
481       {"op": "delete",
482        "table": "b",
483        "where": [["b", "==", 1]]}]]]],
484   [[[{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]},{"uuid":["uuid","<0>"]},{"uuid":["uuid","<1>"]}]
485 [{"uuid":["uuid","<2>"]},{"details":"reference to nonexistent row <3>","error":"referential integrity violation"}]
486 [{"count":1},{"details":"cannot delete a row <0> because of 1 remaining reference(s)","error":"referential integrity violation"}]
487 [{"count":1},{"details":"cannot delete b row <1> because of 1 remaining reference(s)","error":"referential integrity violation"}]
488 [{"count":1},{"details":"cannot delete a row <0> because of 1 remaining reference(s)","error":"referential integrity violation"}]
489 [{"count":1},{"details":"cannot delete b row <1> because of 1 remaining reference(s)","error":"referential integrity violation"}]
490 [{"count":1},{"count":1}]
491 ]])])
492
493 EXECUTION_EXAMPLES