Merge "master" into "next".
[sliver-openvswitch.git] / tests / test-ovsdb.c
index a0476a9..2e12d49 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009 Nicira Networks.
+ * Copyright (c) 2009, 2010 Nicira Networks.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 
 #include "command-line.h"
+#include "dynamic-string.h"
 #include "json.h"
 #include "jsonrpc.h"
 #include "ovsdb-data.h"
@@ -122,14 +123,20 @@ usage(void)
            "    open FILE with FLAGS, run COMMANDs\n"
            "  parse-atomic-type TYPE\n"
            "    parse TYPE as OVSDB atomic type, and re-serialize\n"
+           "  parse-base-type TYPE\n"
+           "    parse TYPE as OVSDB base type, and re-serialize\n"
            "  parse-type JSON\n"
            "    parse JSON as OVSDB type, and re-serialize\n"
            "  parse-atoms TYPE ATOM...\n"
-           "    parse ATOMs as atoms of given TYPE, and re-serialize\n"
+           "    parse JSON ATOMs as atoms of TYPE, and re-serialize\n"
+           "  parse-atom-strings TYPE ATOM...\n"
+           "    parse string ATOMs as atoms of given TYPE, and re-serialize\n"
            "  sort-atoms TYPE ATOM...\n"
-           "    print ATOMs in sorted order, and re-serialize\n"
+           "    print JSON ATOMs in sorted order\n"
            "  parse-data TYPE DATUM...\n"
-           "    parse DATUMs as data of given TYPE, and re-serialize\n"
+           "    parse JSON DATUMs as data of given TYPE, and re-serialize\n"
+           "  parse-data-strings TYPE DATUM...\n"
+           "    parse string DATUMs as data of given TYPE, and re-serialize\n"
            "  parse-column NAME OBJECT\n"
            "    parse column NAME with info OBJECT, and re-serialize\n"
            "  parse-table NAME OBJECT\n"
@@ -152,6 +159,8 @@ usage(void)
            "  query-distinct TABLE [ROW,...] [CONDITION,...] COLUMNS\n"
            "    add each ROW to TABLE, then query and print the rows that\n"
            "    satisfy each CONDITION and have distinct COLUMNS.\n"
+           "  parse-schema JSON\n"
+           "    parse JSON as an OVSDB schema, and re-serialize\n"
            "  transact COMMAND\n"
            "    execute each specified transactional COMMAND:\n"
            "      commit\n"
@@ -228,7 +237,17 @@ static void
 check_ovsdb_error(struct ovsdb_error *error)
 {
     if (error) {
-        ovs_fatal(0, "%s", ovsdb_error_to_string(error));
+        char *s = ovsdb_error_to_string(error);
+        ovsdb_error_destroy(error);
+        ovs_fatal(0, "%s", s);
+    }
+}
+
+static void
+die_if_error(char *error)
+{
+    if (error) {
+        ovs_fatal(0, "%s", error);
     }
 }
 \f
@@ -296,6 +315,7 @@ do_log_io(int argc, char *argv[])
             char *s = ovsdb_error_to_string(error);
             printf("%s: %s failed: %s\n", name, command, s);
             free(s);
+            ovsdb_error_destroy(error);
         } else {
             printf("%s: %s successful\n", name, command);
         }
@@ -305,7 +325,7 @@ do_log_io(int argc, char *argv[])
 }
 
 static void
-do_parse_atomic_type(int argc UNUSED, char *argv[])
+do_parse_atomic_type(int argc OVS_UNUSED, char *argv[])
 {
     enum ovsdb_atomic_type type;
     struct json *json;
@@ -317,7 +337,20 @@ do_parse_atomic_type(int argc UNUSED, char *argv[])
 }
 
 static void
-do_parse_type(int argc UNUSED, char *argv[])
+do_parse_base_type(int argc OVS_UNUSED, char *argv[])
+{
+    struct ovsdb_base_type base;
+    struct json *json;
+
+    json = unbox_json(parse_json(argv[1]));
+    check_ovsdb_error(ovsdb_base_type_from_json(&base, json));
+    json_destroy(json);
+    print_and_free_json(ovsdb_base_type_to_json(&base));
+    ovsdb_base_type_destroy(&base);
+}
+
+static void
+do_parse_type(int argc OVS_UNUSED, char *argv[])
 {
     struct ovsdb_type type;
     struct json *json;
@@ -326,30 +359,63 @@ do_parse_type(int argc UNUSED, char *argv[])
     check_ovsdb_error(ovsdb_type_from_json(&type, json));
     json_destroy(json);
     print_and_free_json(ovsdb_type_to_json(&type));
+    ovsdb_type_destroy(&type);
 }
 
 static void
 do_parse_atoms(int argc, char *argv[])
 {
-    enum ovsdb_atomic_type type;
+    struct ovsdb_base_type base;
     struct json *json;
     int i;
 
     json = unbox_json(parse_json(argv[1]));
-    check_ovsdb_error(ovsdb_atomic_type_from_json(&type, json));
+    check_ovsdb_error(ovsdb_base_type_from_json(&base, json));
     json_destroy(json);
 
     for (i = 2; i < argc; i++) {
+        struct ovsdb_error *error;
         union ovsdb_atom atom;
 
         json = unbox_json(parse_json(argv[i]));
-        check_ovsdb_error(ovsdb_atom_from_json(&atom, type, json, NULL));
+        error = ovsdb_atom_from_json(&atom, &base, json, NULL);
         json_destroy(json);
 
-        print_and_free_json(ovsdb_atom_to_json(&atom, type));
+        if (error) {
+            print_and_free_ovsdb_error(error);
+        } else {
+            print_and_free_json(ovsdb_atom_to_json(&atom, base.type));
+            ovsdb_atom_destroy(&atom, base.type);
+        }
+    }
+    ovsdb_base_type_destroy(&base);
+}
+
+static void
+do_parse_atom_strings(int argc, char *argv[])
+{
+    struct ovsdb_base_type base;
+    struct json *json;
+    int i;
 
-        ovsdb_atom_destroy(&atom, type);
+    json = unbox_json(parse_json(argv[1]));
+    check_ovsdb_error(ovsdb_base_type_from_json(&base, json));
+    json_destroy(json);
+
+    for (i = 2; i < argc; i++) {
+        union ovsdb_atom atom;
+        struct ds out;
+
+        die_if_error(ovsdb_atom_from_string(&atom, &base, argv[i]));
+
+        ds_init(&out);
+        ovsdb_atom_to_string(&atom, base.type, &out);
+        puts(ds_cstr(&out));
+        ds_destroy(&out);
+
+        ovsdb_atom_destroy(&atom, base.type);
     }
+    ovsdb_base_type_destroy(&base);
 }
 
 static void
@@ -374,6 +440,34 @@ do_parse_data(int argc, char *argv[])
 
         ovsdb_datum_destroy(&datum, &type);
     }
+    ovsdb_type_destroy(&type);
+}
+
+static void
+do_parse_data_strings(int argc, char *argv[])
+{
+    struct ovsdb_type type;
+    struct json *json;
+    int i;
+
+    json = unbox_json(parse_json(argv[1]));
+    check_ovsdb_error(ovsdb_type_from_json(&type, json));
+    json_destroy(json);
+
+    for (i = 2; i < argc; i++) {
+        struct ovsdb_datum datum;
+        struct ds out;
+
+        die_if_error(ovsdb_datum_from_string(&datum, &type, argv[i]));
+
+        ds_init(&out);
+        ovsdb_datum_to_string(&datum, &type, &out);
+        puts(ds_cstr(&out));
+        ds_destroy(&out);
+
+        ovsdb_datum_destroy(&datum, &type);
+    }
+    ovsdb_type_destroy(&type);
 }
 
 static enum ovsdb_atomic_type compare_atoms_atomic_type;
@@ -388,16 +482,16 @@ compare_atoms(const void *a_, const void *b_)
 }
 
 static void
-do_sort_atoms(int argc UNUSED, char *argv[])
+do_sort_atoms(int argc OVS_UNUSED, char *argv[])
 {
-    enum ovsdb_atomic_type type;
+    struct ovsdb_base_type base;
     union ovsdb_atom *atoms;
     struct json *json, **json_atoms;
     size_t n_atoms;
     int i;
 
     json = unbox_json(parse_json(argv[1]));
-    check_ovsdb_error(ovsdb_atomic_type_from_json(&type, json));
+    check_ovsdb_error(ovsdb_base_type_from_json(&base, json));
     json_destroy(json);
 
     json = unbox_json(parse_json(argv[2]));
@@ -409,26 +503,28 @@ do_sort_atoms(int argc UNUSED, char *argv[])
     n_atoms = json->u.array.n;
     atoms = xmalloc(n_atoms * sizeof *atoms);
     for (i = 0; i < n_atoms; i++) {
-        check_ovsdb_error(ovsdb_atom_from_json(&atoms[i], type,
+        check_ovsdb_error(ovsdb_atom_from_json(&atoms[i], &base,
                                                json->u.array.elems[i], NULL));
     }
     json_destroy(json);
 
     /* Sort atoms. */
-    compare_atoms_atomic_type = type;
+    compare_atoms_atomic_type = base.type;
     qsort(atoms, n_atoms, sizeof *atoms, compare_atoms);
 
     /* Convert internal representation back to JSON. */
     json_atoms = xmalloc(n_atoms * sizeof *json_atoms);
     for (i = 0; i < n_atoms; i++) {
-        json_atoms[i] = ovsdb_atom_to_json(&atoms[i], type);
-        ovsdb_atom_destroy(&atoms[i], type);
+        json_atoms[i] = ovsdb_atom_to_json(&atoms[i], base.type);
+        ovsdb_atom_destroy(&atoms[i], base.type);
     }
     print_and_free_json(json_array_create(json_atoms, n_atoms));
+    free(atoms);
+    ovsdb_base_type_destroy(&base);
 }
 
 static void
-do_parse_column(int argc UNUSED, char *argv[])
+do_parse_column(int argc OVS_UNUSED, char *argv[])
 {
     struct ovsdb_column *column;
     struct json *json;
@@ -441,7 +537,7 @@ do_parse_column(int argc UNUSED, char *argv[])
 }
 
 static void
-do_parse_table(int argc UNUSED, char *argv[])
+do_parse_table(int argc OVS_UNUSED, char *argv[])
 {
     struct ovsdb_table_schema *ts;
     struct json *json;
@@ -561,6 +657,10 @@ do_compare_rows(int argc, char *argv[])
             }
         }
     }
+    for (i = 0; i < n_rows; i++) {
+        ovsdb_row_destroy(rows[i]);
+        free(names[i]);
+    }
     free(rows);
     free(names);
 
@@ -605,7 +705,7 @@ do_parse_conditions(int argc, char *argv[])
 }
 
 static void
-do_evaluate_conditions(int argc UNUSED, char *argv[])
+do_evaluate_conditions(int argc OVS_UNUSED, char *argv[])
 {
     struct ovsdb_table_schema *ts;
     struct ovsdb_table *table;
@@ -665,9 +765,11 @@ do_evaluate_conditions(int argc UNUSED, char *argv[])
     for (i = 0; i < n_conditions; i++) {
         ovsdb_condition_destroy(&conditions[i]);
     }
+    free(conditions);
     for (i = 0; i < n_rows; i++) {
         ovsdb_row_destroy(rows[i]);
     }
+    free(rows);
     ovsdb_table_destroy(table); /* Also destroys 'ts'. */
 }
 
@@ -708,7 +810,7 @@ do_parse_mutations(int argc, char *argv[])
 }
 
 static void
-do_execute_mutations(int argc UNUSED, char *argv[])
+do_execute_mutations(int argc OVS_UNUSED, char *argv[])
 {
     struct ovsdb_table_schema *ts;
     struct ovsdb_table *table;
@@ -794,9 +896,11 @@ do_execute_mutations(int argc UNUSED, char *argv[])
     for (i = 0; i < n_sets; i++) {
         ovsdb_mutation_set_destroy(&sets[i]);
     }
+    free(sets);
     for (i = 0; i < n_rows; i++) {
         ovsdb_row_destroy(rows[i]);
     }
+    free(rows);
     ovsdb_table_destroy(table); /* Also destroys 'ts'. */
 }
 
@@ -822,7 +926,7 @@ do_query_cb(const struct ovsdb_row *row, void *cbdata_)
 }
 
 static void
-do_query(int argc UNUSED, char *argv[])
+do_query(int argc OVS_UNUSED, char *argv[])
 {
     struct do_query_cbdata cbdata;
     struct ovsdb_table_schema *ts;
@@ -912,7 +1016,7 @@ struct do_query_distinct_row {
 };
 
 static void
-do_query_distinct(int argc UNUSED, char *argv[])
+do_query_distinct(int argc OVS_UNUSED, char *argv[])
 {
     struct ovsdb_column_set columns;
     struct ovsdb_table_schema *ts;
@@ -1037,7 +1141,20 @@ do_query_distinct(int argc UNUSED, char *argv[])
 }
 
 static void
-do_execute(int argc UNUSED, char *argv[])
+do_parse_schema(int argc OVS_UNUSED, char *argv[])
+{
+    struct ovsdb_schema *schema;
+    struct json *json;
+
+    json = parse_json(argv[1]);
+    check_ovsdb_error(ovsdb_schema_from_json(json, &schema));
+    json_destroy(json);
+    print_and_free_json(ovsdb_schema_to_json(schema));
+    ovsdb_schema_destroy(schema);
+}
+
+static void
+do_execute(int argc OVS_UNUSED, char *argv[])
 {
     struct ovsdb_schema *schema;
     struct json *json;
@@ -1058,6 +1175,7 @@ do_execute(int argc UNUSED, char *argv[])
         result = ovsdb_execute(db, params, 0, NULL);
         s = json_to_string(result, JSSF_SORT);
         printf("%s\n", s);
+        free(s);
         json_destroy(params);
         json_destroy(result);
     }
@@ -1079,13 +1197,14 @@ do_trigger_dump(struct test_trigger *t, long long int now, const char *title)
     result = ovsdb_trigger_steal_result(&t->trigger);
     s = json_to_string(result, JSSF_SORT);
     printf("t=%lld: trigger %d (%s): %s\n", now, t->number, title, s);
+    free(s);
     json_destroy(result);
     ovsdb_trigger_destroy(&t->trigger);
     free(t);
 }
 
 static void
-do_trigger(int argc UNUSED, char *argv[])
+do_trigger(int argc OVS_UNUSED, char *argv[])
 {
     struct ovsdb_schema *schema;
     struct list completions;
@@ -1140,7 +1259,7 @@ do_trigger(int argc UNUSED, char *argv[])
 }
 
 static void
-do_help(int argc UNUSED, char *argv[] UNUSED)
+do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
     usage();
 }
@@ -1152,14 +1271,14 @@ static struct ovsdb_txn *do_transact_txn;
 static struct ovsdb_table *do_transact_table;
 
 static void
-do_transact_commit(int argc UNUSED, char *argv[] UNUSED)
+do_transact_commit(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
     ovsdb_txn_commit(do_transact_txn, false);
     do_transact_txn = NULL;
 }
 
 static void
-do_transact_abort(int argc UNUSED, char *argv[] UNUSED)
+do_transact_abort(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
     ovsdb_txn_abort(do_transact_txn);
     do_transact_txn = NULL;
@@ -1219,7 +1338,7 @@ do_transact_set_i_j(struct ovsdb_row *row,
 }
 
 static void
-do_transact_insert(int argc UNUSED, char *argv[] UNUSED)
+do_transact_insert(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
     struct ovsdb_row *row;
     struct uuid *uuid;
@@ -1241,14 +1360,14 @@ do_transact_insert(int argc UNUSED, char *argv[] UNUSED)
 }
 
 static void
-do_transact_delete(int argc UNUSED, char *argv[] UNUSED)
+do_transact_delete(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
     const struct ovsdb_row *row = do_transact_find_row(argv[1]);
     ovsdb_txn_row_delete(do_transact_txn, row);
 }
 
 static void
-do_transact_modify(int argc UNUSED, char *argv[] UNUSED)
+do_transact_modify(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
     const struct ovsdb_row *row_ro;
     struct ovsdb_row *row_rw;
@@ -1268,7 +1387,7 @@ compare_rows_by_uuid(const void *a_, const void *b_)
 }
 
 static void
-do_transact_print(int argc UNUSED, char *argv[] UNUSED)
+do_transact_print(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 {
     const struct ovsdb_row **rows;
     const struct ovsdb_row *row;
@@ -1553,6 +1672,7 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
     char *cmd, *save_ptr1 = NULL;
     struct ovsdb_idl_txn *txn;
     enum ovsdb_idl_txn_status status;
+    bool increment = false;
 
     txn = ovsdb_idl_txn_create(idl);
     for (cmd = strtok_r(commands, ",", &save_ptr1); cmd;
@@ -1614,6 +1734,12 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
                           "i=%d", atoi(arg1));
             }
             idltest_simple_delete(s);
+        } else if (!strcmp(name, "increment")) {
+            if (!arg2 || arg3) {
+                ovs_fatal(0, "\"set\" command requires 2 arguments");
+            }
+            ovsdb_idl_txn_increment(txn, arg1, arg2, NULL);
+            increment = true;
         } else {
             ovs_fatal(0, "unknown command %s", name);
         }
@@ -1625,8 +1751,13 @@ idl_set(struct ovsdb_idl *idl, char *commands, int step)
         ovsdb_idl_txn_wait(txn);
         poll_block();
     }
-    printf("%03d: commit, status=%s\n",
+    printf("%03d: commit, status=%s",
            step, ovsdb_idl_txn_status_to_string(status));
+    if (increment) {
+        printf(", increment=%"PRId64,
+               ovsdb_idl_txn_get_increment_new_value(txn));
+    }
+    putchar('\n');
     ovsdb_idl_txn_destroy(txn);
 }
 
@@ -1642,6 +1773,8 @@ do_idl(int argc, char *argv[])
     int error;
     int i;
 
+    idltest_init();
+
     idl = ovsdb_idl_create(argv[1], &idltest_idl_class);
     if (argc > 2) {
         struct stream *stream;
@@ -1655,20 +1788,28 @@ do_idl(int argc, char *argv[])
         rpc = NULL;
     }
 
+    setvbuf(stdout, NULL, _IOLBF, 0);
+
     symtab = ovsdb_symbol_table_create();
     for (i = 2; i < argc; i++) {
+        char *arg = argv[i];
         struct jsonrpc_msg *request, *reply;
         int error;
 
-        seqno = print_updated_idl(idl, rpc, step++, seqno);
+        if (*arg == '+') {
+            /* The previous transaction didn't change anything. */
+            arg++;
+        } else {
+            seqno = print_updated_idl(idl, rpc, step++, seqno);
+        }
 
-        if (!strcmp(argv[i], "reconnect")) {
+        if (!strcmp(arg, "reconnect")) {
             printf("%03d: reconnect\n", step++);
             ovsdb_idl_force_reconnect(idl);
-        } else if (argv[i][0] != '[') {
-            idl_set(idl, argv[i], step++);
+        } else if (arg[0] != '[') {
+            idl_set(idl, arg, step++);
         } else {
-            struct json *json = parse_json(argv[i]);
+            struct json *json = parse_json(arg);
             substitute_uuids(json, symtab);
             request = jsonrpc_create_request("transact", json, NULL);
             error = jsonrpc_transact_block(rpc, request, &reply);
@@ -1697,9 +1838,12 @@ do_idl(int argc, char *argv[])
 static struct command all_commands[] = {
     { "log-io", 2, INT_MAX, do_log_io },
     { "parse-atomic-type", 1, 1, do_parse_atomic_type },
+    { "parse-base-type", 1, 1, do_parse_base_type },
     { "parse-type", 1, 1, do_parse_type },
     { "parse-atoms", 2, INT_MAX, do_parse_atoms },
+    { "parse-atom-strings", 2, INT_MAX, do_parse_atom_strings },
     { "parse-data", 2, INT_MAX, do_parse_data },
+    { "parse-data-strings", 2, INT_MAX, do_parse_data_strings },
     { "sort-atoms", 2, 2, do_sort_atoms },
     { "parse-column", 2, 2, do_parse_column },
     { "parse-table", 2, 2, do_parse_table },
@@ -1712,6 +1856,7 @@ static struct command all_commands[] = {
     { "query", 3, 3, do_query },
     { "query-distinct", 4, 4, do_query_distinct },
     { "transact", 1, INT_MAX, do_transact },
+    { "parse-schema", 1, 1, do_parse_schema },
     { "execute", 2, INT_MAX, do_execute },
     { "trigger", 2, INT_MAX, do_trigger },
     { "idl", 1, INT_MAX, do_idl },