[ovs-dev] [PATCH 5/5] tests:ovsdb-idl: Add testing for compound index feature

Rodriguez Betancourt, Esteban estebarb at hpe.com
Wed Mar 9 00:05:46 UTC 2016


This commit includes the tests to verify compound index behavior.
Tests are divide in single and double column indexes and skiplist.

Signed-off-by: Arnoldo Lutz Guevara <arnoldo.lutz.guevara at hpe.com>
Signed-off-by: Esteban Rodriguez Betancourt <estebarb at hpe.com>
Co-authored-by: Arnoldo Lutz Guevara <arnoldo.lutz.guevara at hpe.com>
Co-authored-by: Esteban Rodriguez Betancourt <estebarb at hpe.com>
---
 tests/.gitignore        |   1 +
 tests/automake.mk       |   2 +
 tests/idltest.ovsschema |   6 +-
 tests/library.at        |  11 ++
 tests/ovsdb-idl.at      | 267 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-ovsdb.c      | 213 +++++++++++++++++++++++++++++++++++++-
 tests/test-skiplist.c   | 210 +++++++++++++++++++++++++++++++++++++
 7 files changed, 707 insertions(+), 3 deletions(-)
 create mode 100644 tests/test-skiplist.c

diff --git a/tests/.gitignore b/tests/.gitignore
index f4540a3..ed017c1 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -38,6 +38,7 @@
 /test-rstp
 /test-sflow
 /test-sha1
+/test-skiplist
 /test-stp
 /test-strtok_r
 /test-timeval
diff --git a/tests/automake.mk b/tests/automake.mk
index ef0a2f6..54955b9 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -167,6 +167,7 @@ valgrind_wrappers = \
 	tests/valgrind/test-reconnect \
 	tests/valgrind/test-rstp \
 	tests/valgrind/test-sha1 \
+	tests/valgrind/test-skiplist \
 	tests/valgrind/test-stp \
 	tests/valgrind/test-type-props \
 	tests/valgrind/test-unix-socket \
@@ -313,6 +314,7 @@ tests_ovstest_SOURCES = \
 	tests/test-rstp.c \
 	tests/test-sflow.c \
 	tests/test-sha1.c \
+	tests/test-skiplist.c \
 	tests/test-stp.c \
 	tests/test-unixctl.c \
 	tests/test-util.c \
diff --git a/tests/idltest.ovsschema b/tests/idltest.ovsschema
index 1d073aa..6c7f8a9 100644
--- a/tests/idltest.ovsschema
+++ b/tests/idltest.ovsschema
@@ -34,7 +34,8 @@
             "min": 0
           }
         }
-      }
+      },
+      "isRoot":true
     }, 
     "link2": {
       "columns": {
@@ -104,7 +105,8 @@
             "min": 0
           }
         }
-      }
+      },
+      "isRoot":true
     }
   }
 }
diff --git a/tests/library.at b/tests/library.at
index d5dcb12..4542156 100644
--- a/tests/library.at
+++ b/tests/library.at
@@ -51,6 +51,17 @@ AT_CHECK([ovstest test-sha1], [0], [.........
 ])
 AT_CLEANUP
 
+AT_SETUP([test skiplist])
+AT_KEYWORDS([skiplist])
+AT_CHECK([ovstest test-skiplist], [0], [skiplist insert
+skiplist delete
+skiplist find
+skiplist forward_to
+skiplist random
+
+])
+AT_CLEANUP
+
 AT_SETUP([test type properties])
 AT_CHECK([test-type-props])
 AT_CLEANUP
diff --git a/tests/ovsdb-idl.at b/tests/ovsdb-idl.at
index ebf82a5..f4a90fd 100644
--- a/tests/ovsdb-idl.at
+++ b/tests/ovsdb-idl.at
@@ -776,3 +776,270 @@ OVSDB_CHECK_IDL_TRACK([track, simple idl, initially empty, various ops],
 014: updated columns: ba i ia r ra s
 015: done
 ]])
+
+# Tests to verify the functionality of the one column compound index.
+# It tests index for one column string and integer indexes.
+# The run of test-ovsdb generates the output of the display of data using the different indexes defined in
+# the program.
+# Then, some at_checks are used to verify the correctness of the corresponding index as well as the existence
+# of all the rows involved in the test.
+m4_define([OVSDB_CHECK_IDL_COMPOUND_INDEX_SINGLE_COLUMN_C],
+  [AT_SETUP([$1 - C])
+   AT_KEYWORDS([ovsdb server idl compound_index_single_column compound_index positive $5])
+   AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema],
+                  [0], [stdout], [ignore])
+   AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   m4_if([$2], [], [],
+     [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore], [kill `cat pid`])])
+# Generate the data to be tested.
+   AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 -c idl-compound-index unix:socket $3],
+            [0], [stdout], [ignore], [kill `cat pid`])
+# Filter the rows of data that corresponds to the string index eliminating the extra columns of data.
+# This is done to verifiy that the output data is in the correct and expected order.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: s=.*' | sed -e 's/ i=.*//g']],
+            [0], [$4], [], [kill `cat pid`])
+# Here, the data is filtered and sorted in order to have all the rows in the index and be
+# able to determined that all the involved rows are present.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: s=.*' | sort -k 1,1n -k 2,2 -k 3,3]],
+            [0], [$5], [], [kill `cat pid`])
+# Filter the rows of data that corresponds to the integer index eliminating the extra columns of data.
+# This is done to verifiy that the output data is in the correct and expected order.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: i=.*' | sed -e 's/ s=.*//g']],
+            [0], [$6], [], [kill `cat pid`])
+# Here again, the data is filtered and sorted in order to have all the rows in the index and be
+# able to determined that all the involved rows are present.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: i=.*' | sort -k 1,1n -k 2,2 -k 3,3]],
+            [0], [$7], [], [kill `cat pid`])
+   OVSDB_SERVER_SHUTDOWN
+   AT_CLEANUP])
+
+OVSDB_CHECK_IDL_COMPOUND_INDEX_SINGLE_COLUMN_C([Compound_index, single column test ],
+    [['["idltest",
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 1, "b":true, "r":101.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 2, "b":false, "r":102.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 10, "b":true, "r":110.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 1, "b":false, "r":110.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 2, "b":true, "r":120.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 2, "b":true, "r":122.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 4, "b":true, "r":130.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List005", "i": 5, "b":true, "r":130.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List020", "i": 20, "b":true, "r":220.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List020", "i": 19, "b":true, "r":219.0}}
+      ]']],
+    [idl_compound_index_single_column],
+    [001: s=List000
+001: s=List000
+001: s=List000
+001: s=List001
+001: s=List001
+001: s=List001
+001: s=List001
+001: s=List005
+001: s=List020
+001: s=List020
+003: s=List001
+003: s=List001
+003: s=List001
+003: s=List001
+],
+[001: s=List000 i=1 b=True r=101.000000
+001: s=List000 i=10 b=True r=110.000000
+001: s=List000 i=2 b=False r=102.000000
+001: s=List001 i=1 b=False r=110.000000
+001: s=List001 i=2 b=True r=120.000000
+001: s=List001 i=2 b=True r=122.000000
+001: s=List001 i=4 b=True r=130.000000
+001: s=List005 i=5 b=True r=130.000000
+001: s=List020 i=19 b=True r=219.000000
+001: s=List020 i=20 b=True r=220.000000
+003: s=List001 i=1 b=False r=110.000000
+003: s=List001 i=2 b=True r=120.000000
+003: s=List001 i=2 b=True r=122.000000
+003: s=List001 i=4 b=True r=130.000000
+],
+[002: i=1
+002: i=1
+002: i=2
+002: i=2
+002: i=2
+002: i=4
+002: i=5
+002: i=10
+002: i=19
+002: i=20
+004: i=5
+005: i=4
+005: i=5
+006: i=5
+006: i=10
+006: i=19
+006: i=20
+006: i=54
+],
+[002: i=1 s=List000 b=True r=101.000000
+002: i=1 s=List001 b=False r=110.000000
+002: i=10 s=List000 b=True r=110.000000
+002: i=19 s=List020 b=True r=219.000000
+002: i=2 s=List000 b=False r=102.000000
+002: i=2 s=List001 b=True r=120.000000
+002: i=2 s=List001 b=True r=122.000000
+002: i=20 s=List020 b=True r=220.000000
+002: i=4 s=List001 b=True r=130.000000
+002: i=5 s=List005 b=True r=130.000000
+004: i=5 s=List005 b=True r=130.000000
+005: i=4 s=List001 b=True r=130.000000
+005: i=5 s=List005 b=True r=130.000000
+006: i=10 s=List000 b=True r=110.000000
+006: i=19 s=List020 b=True r=219.000000
+006: i=20 s=List020 b=True r=220.000000
+006: i=5 s=List005 b=True r=130.000000
+006: i=54 s=Lista054 b=False r=0.000000
+])
+
+# Tests to verify the functionality of two column compound index.
+# It tests index for two columns using string and integer fields.
+# The run of test-ovsdb generates the output of the display of data using the different indexes defined in
+# the program.
+# Then, some at_checks are used to verify the correctness of the corresponding index as well as the existence
+# of all the rows involved in the test.
+m4_define([OVSDB_CHECK_IDL_COMPOUND_INDEX_DOUBLE_COLUMN_C],
+  [AT_SETUP([$1 - C])
+   AT_KEYWORDS([ovsdb server idl compound_index_double_column compound_index positive $5])
+   AT_CHECK([ovsdb-tool create db $abs_srcdir/idltest.ovsschema],
+                  [0], [stdout], [ignore])
+   AT_CHECK([ovsdb-server '-vPATTERN:console:ovsdb-server|%c|%m' --detach --no-chdir --pidfile="`pwd`"/pid --remote=punix:socket --unixctl="`pwd`"/unixctl db], [0], [ignore], [ignore])
+   m4_if([$2], [], [],
+     [AT_CHECK([ovsdb-client transact unix:socket $2], [0], [ignore], [ignore], [kill `cat pid`])])
+# Generate the data to be tested.
+   AT_CHECK([test-ovsdb '-vPATTERN:console:test-ovsdb|%c|%m' -vjsonrpc -t10 -c idl-compound-index unix:socket $3],
+            [0], [stdout], [ignore], [kill `cat pid`])
+# Filter the rows of data that corresponds to the string-integer index eliminating the extra columns of data.
+# This is done to verifiy that the output data is in the correct and expected order.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: s=.*' | sed -e 's/ b=.*//g']],
+            [0], [$4], [], [kill `cat pid`])
+# Here, the data is filtered and sorted in order to have all the rows in the index and be
+# able to determined that all the involved rows are present.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: s=.*' | sort -k 1,1n -k 2,2 -k 3,3]],
+            [0], [$5], [], [kill `cat pid`])
+# Filter the rows of data that corresponds to the integer index eliminating the extra columns of data.
+# This is done to verifiy that the output data is in the correct and expected order.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: i=.*' | sed -e 's/ b=.*//g']],
+            [0], [$6], [], [kill `cat pid`])
+# Here again, the data is filtered and sorted in order to have all the rows in the index and be
+# able to determined that all the involved rows are present.
+   AT_CHECK([[cat stdout | grep -oh '[0-9]\{3\}: i=.*' | sort -k 1,1n -k 2,2 -k 3,3]],
+            [0], [$7], [], [kill `cat pid`])
+   OVSDB_SERVER_SHUTDOWN
+   AT_CLEANUP])
+
+OVSDB_CHECK_IDL_COMPOUND_INDEX_DOUBLE_COLUMN_C([Compound_index, double column test ],
+    [['["idltest",
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 1, "b":true, "r":101.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 2, "b":false, "r":102.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List000", "i": 10, "b":true, "r":110.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 1, "b":false, "r":110.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 2, "b":true, "r":120.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 2, "b":true, "r":122.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List001", "i": 4, "b":true, "r":130.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List005", "i": 5, "b":true, "r":130.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List020", "i": 20, "b":true, "r":220.0}},
+      {"op": "insert", "table": "simple", "row": {"s":"List020", "i": 19, "b":true, "r":219.0}}
+      ]']],
+    [idl_compound_index_double_column],
+    [001: s=List000 i=1
+001: s=List000 i=2
+001: s=List000 i=10
+001: s=List001 i=1
+001: s=List001 i=2
+001: s=List001 i=2
+001: s=List001 i=4
+001: s=List005 i=5
+001: s=List020 i=19
+001: s=List020 i=20
+002: s=List000 i=10
+002: s=List000 i=2
+002: s=List000 i=1
+002: s=List001 i=4
+002: s=List001 i=2
+002: s=List001 i=2
+002: s=List001 i=1
+002: s=List005 i=5
+002: s=List020 i=20
+002: s=List020 i=19
+003: s=List000 i=10
+004: s=List001 i=1
+004: s=List001 i=2
+004: s=List001 i=2
+004: s=List001 i=4
+004: s=List005 i=5
+],
+    [001: s=List000 i=1 b=True r=101.000000
+001: s=List000 i=10 b=True r=110.000000
+001: s=List000 i=2 b=False r=102.000000
+001: s=List001 i=1 b=False r=110.000000
+001: s=List001 i=2 b=True r=120.000000
+001: s=List001 i=2 b=True r=122.000000
+001: s=List001 i=4 b=True r=130.000000
+001: s=List005 i=5 b=True r=130.000000
+001: s=List020 i=19 b=True r=219.000000
+001: s=List020 i=20 b=True r=220.000000
+002: s=List000 i=1 b=True r=101.000000
+002: s=List000 i=10 b=True r=110.000000
+002: s=List000 i=2 b=False r=102.000000
+002: s=List001 i=1 b=False r=110.000000
+002: s=List001 i=2 b=True r=120.000000
+002: s=List001 i=2 b=True r=122.000000
+002: s=List001 i=4 b=True r=130.000000
+002: s=List005 i=5 b=True r=130.000000
+002: s=List020 i=19 b=True r=219.000000
+002: s=List020 i=20 b=True r=220.000000
+003: s=List000 i=10 b=True r=110.000000
+004: s=List001 i=1 b=False r=110.000000
+004: s=List001 i=2 b=True r=120.000000
+004: s=List001 i=2 b=True r=122.000000
+004: s=List001 i=4 b=True r=130.000000
+004: s=List005 i=5 b=True r=130.000000
+],
+    [005: i=1 s=List000
+005: i=1 s=List001
+005: i=2 s=List000
+005: i=2 s=List001
+005: i=2 s=List001
+005: i=4 s=List001
+005: i=5 s=List005
+005: i=10 s=List000
+005: i=19 s=List020
+005: i=20 s=List020
+006: i=20 s=List020
+006: i=19 s=List020
+006: i=10 s=List000
+006: i=5 s=List005
+006: i=4 s=List001
+006: i=2 s=List000
+006: i=2 s=List001
+006: i=2 s=List001
+006: i=1 s=List000
+006: i=1 s=List001
+],
+    [005: i=1 s=List000 b=True r=101.000000
+005: i=1 s=List001 b=False r=110.000000
+005: i=10 s=List000 b=True r=110.000000
+005: i=19 s=List020 b=True r=219.000000
+005: i=2 s=List000 b=False r=102.000000
+005: i=2 s=List001 b=True r=120.000000
+005: i=2 s=List001 b=True r=122.000000
+005: i=20 s=List020 b=True r=220.000000
+005: i=4 s=List001 b=True r=130.000000
+005: i=5 s=List005 b=True r=130.000000
+006: i=1 s=List000 b=True r=101.000000
+006: i=1 s=List001 b=False r=110.000000
+006: i=10 s=List000 b=True r=110.000000
+006: i=19 s=List020 b=True r=219.000000
+006: i=2 s=List000 b=False r=102.000000
+006: i=2 s=List001 b=True r=120.000000
+006: i=2 s=List001 b=True r=122.000000
+006: i=20 s=List020 b=True r=220.000000
+006: i=4 s=List001 b=True r=130.000000
+006: i=5 s=List005 b=True r=130.000000
+])
+
diff --git a/tests/test-ovsdb.c b/tests/test-ovsdb.c
index 670a141..be39ffc 100644
--- a/tests/test-ovsdb.c
+++ b/tests/test-ovsdb.c
@@ -197,7 +197,14 @@ usage(void)
            "    connect to SERVER and dump the contents of the database\n"
            "    as seen initially by the IDL implementation and after\n"
            "    executing each TRANSACTION.  (Each TRANSACTION must modify\n"
-           "    the database or this command will hang.)\n",
+           "    the database or this command will hang.)\n"
+           "  idl-compound-index TEST_TO_EXECUTE\n"
+           "    Execute the tests to verify compound-index feature.\n"
+           "    The TEST_TO_EXECUTE are:\n"
+           "        idl_compound_index_single_column:\n"
+           "            test for indexes using one column as part of the index.\n"
+           "        idl_compound_index_double_column:\n"
+           "            test for indexes using two columns as part of index.\n",
            program_name, program_name);
     vlog_usage();
     printf("\nOther options:\n"
@@ -2178,6 +2185,209 @@ do_idl(struct ovs_cmdl_context *ctx)
     printf("%03d: done\n", step);
 }
 
+static int
+test_idl_compound_index_single_column(struct ovsdb_idl *idl,
+        struct ovsdb_idl_index_cursor* sCursor,
+        struct ovsdb_idl_index_cursor* iCursor)
+{
+    const struct idltest_simple* myRow;
+    struct ovsdb_idl_txn *txn;
+    int step=0;
+
+     /* Display records by string index -> sCursor */
+     ++step;
+     IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, sCursor)
+     {
+         printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, myRow->b?"True":"False", myRow->r);
+     }
+     /* Display records by integer index -> iCursor */
+     ++step;
+     IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, iCursor)
+     {
+         printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step,  myRow->i,myRow->s, myRow->b?"True":"False", myRow->r);
+     }
+     /* Display records by string index -> sCursor with filtering where s=\"List001\ */
+     ++step;
+     struct idltest_simple equal;
+     equal.s = "List001";
+     IDLTEST_SIMPLE_FOR_EACH_EQUAL(myRow, sCursor, &equal)
+     {
+         printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, myRow->b?"True":"False", myRow->r);
+     }
+     /* Display records by integer index -> iCursor with filtering where i=5 */
+     ++step;
+     equal.i=5;
+     IDLTEST_SIMPLE_FOR_EACH_EQUAL(myRow, iCursor, &equal) {
+         printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step,  myRow->i,myRow->s, myRow->b?"True":"False", myRow->r);
+     }
+     /* Display records by integer index -> iCursor in range i=[3,7] */
+     ++step;
+     struct idltest_simple from, to;
+     from.i = 3;
+     to.i = 7;
+     IDLTEST_SIMPLE_FOR_EACH_RANGE(myRow, iCursor, &from, &to)
+     {
+         printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step,  myRow->i,myRow->s, myRow->b?"True":"False", myRow->r);
+     }
+     /* Delete record i=4 and insert i=54 by integer index -> iCursor */
+     ++step;
+     struct idltest_simple toDelete, *toInsert;
+     toDelete.i = 4;
+     myRow = &toDelete;
+     myRow = idltest_simple_index_find(iCursor, myRow);
+     txn = ovsdb_idl_txn_create(idl);
+     idltest_simple_delete(myRow);
+     toInsert = idltest_simple_insert(txn);
+     idltest_simple_set_i(toInsert, 54);
+     idltest_simple_set_s(toInsert, "Lista054");
+     ovsdb_idl_txn_commit_block(txn);
+     ovsdb_idl_txn_destroy(txn);
+     to.i = 60;
+     IDLTEST_SIMPLE_FOR_EACH_RANGE(myRow, iCursor, &from, &to)
+     {
+         printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step,  myRow->i, myRow->s, myRow->b?"True":"False", myRow->r);
+     }
+     return step;
+}
+
+static int
+test_idl_compound_index_double_column(struct ovsdb_idl_index_cursor* siCursor,
+        struct ovsdb_idl_index_cursor* sidCursor,
+        struct ovsdb_idl_index_cursor* isCursor,
+        struct ovsdb_idl_index_cursor* idsCursor)
+{
+    const struct idltest_simple* myRow;
+    int step = 0;
+
+    /* Display records by string-integer index -> siCursor */
+    step++;
+    IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, siCursor)
+    {
+        printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records by string-integer(down order) index -> sidCursor */
+    step++;
+    IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, sidCursor)
+    {
+        printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records by string-integer index -> siCursor with filtering where s="List000" and i=10 */
+    step++;
+    struct idltest_simple equal;
+    equal.s = "List000";
+    equal.i = 10;
+    IDLTEST_SIMPLE_FOR_EACH_EQUAL(myRow, siCursor, &equal)
+    {
+        printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records by string-integer index -> siCursor in range i=[0,100] and s=[\"List002\",\"List003\"] */
+    step++;
+    struct idltest_simple from, to;
+    from.i = 0;
+    from.s = "List001";
+    to.i = 100;
+    to.s = "List005";
+    IDLTEST_SIMPLE_FOR_EACH_RANGE(myRow, siCursor, &from, &to)
+    {
+        printf("%03d: s=%s i=%"PRId64" b=%s r=%f\n", step, myRow->s, myRow->i, myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records using integer-string index. */
+    step++;
+    IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, isCursor) {
+        printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i, myRow->s, myRow->b?"True":"False", myRow->r);
+    }
+    /* Display records using integer(descend)-string index. */
+    step++;
+    IDLTEST_SIMPLE_FOR_EACH_BYINDEX(myRow, idsCursor) {
+        printf("%03d: i=%"PRId64" s=%s b=%s r=%f\n", step, myRow->i, myRow->s, myRow->b?"True":"False", myRow->r);
+    }
+    return step;
+}
+
+static void
+do_idl_compound_index(struct ovs_cmdl_context *ctx)
+{
+    struct ovsdb_idl *idl;
+    struct ovsdb_idl_index_cursor sCursor, iCursor, siCursor, sidCursor,
+                    isCursor, idsCursor;
+    enum TESTS { IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN,
+            IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN
+    };
+    int step = 0;
+    int i;
+
+    idltest_init();
+
+    idl = ovsdb_idl_create(ctx->argv[1], &idltest_idl_class, false, true);
+
+    /* Add tables/columns and initialize index data needed for tests */
+    ovsdb_idl_add_table(idl, &idltest_table_simple);
+    ovsdb_idl_add_column(idl, &idltest_simple_col_s);
+    ovsdb_idl_add_column(idl, &idltest_simple_col_i);
+    ovsdb_idl_add_column(idl, &idltest_simple_col_r);
+    ovsdb_idl_add_column(idl, &idltest_simple_col_b);
+
+    struct ovsdb_idl_index *index;
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, "string");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, "integer");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_ASC, NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, "string-integer");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, NULL);
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_ASC, NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, "string-integerd");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, NULL);
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_DESC, NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, "integer-string");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_ASC, NULL);
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, NULL);
+
+    index = ovsdb_idl_create_index(idl, &idltest_table_simple, "integerd-string");
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_i, OVSDB_INDEX_DESC, NULL);
+    ovsdb_idl_index_add_column(index, &idltest_simple_col_s, OVSDB_INDEX_ASC, NULL);
+
+    /* wait for replica to be updated */
+    ovsdb_idl_get_initial_snapshot(idl);
+
+    /* Initialize cursors to be used by indexes */
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "string", &sCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "integer", &iCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "string-integer", &siCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "string-integerd", &sidCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "integer-string", &isCursor);
+    ovsdb_idl_initialize_cursor(idl, &idltest_table_simple, "integerd-string", &idsCursor);
+
+    setvbuf(stdout, NULL, _IONBF, 0);
+    int test_to_run = -1;
+    for (i = 2; i < ctx->argc; i++) {
+        char *arg = ctx->argv[i];
+
+        if(strcmp(arg,"idl_compound_index_single_column")== 0) {
+            test_to_run = IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN;
+        } else if(strcmp(arg, "idl_compound_index_double_column")==0) {
+            test_to_run = IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN;
+        }
+
+        switch(test_to_run) {
+            case IDL_COMPOUND_INDEX_WITH_SINGLE_COLUMN:
+                test_idl_compound_index_single_column(idl, &sCursor, &iCursor);
+                break;
+            case IDL_COMPOUND_INDEX_WITH_DOUBLE_COLUMN:
+                test_idl_compound_index_double_column(&siCursor,
+                        &sidCursor, &isCursor, &idsCursor);
+                break;
+            default:
+                printf("%03d: Test %s not implemented.\n", step++, arg);
+        }
+    }
+    ovsdb_idl_destroy(idl);
+    printf("%03d: done\n", step);
+}
+
 static struct ovs_cmdl_command all_commands[] = {
     { "log-io", NULL, 2, INT_MAX, do_log_io },
     { "default-atoms", NULL, 0, 0, do_default_atoms },
@@ -2206,6 +2416,7 @@ static struct ovs_cmdl_command all_commands[] = {
     { "execute", NULL, 2, INT_MAX, do_execute },
     { "trigger", NULL, 2, INT_MAX, do_trigger },
     { "idl", NULL, 1, INT_MAX, do_idl },
+    { "idl-compound-index", NULL, 2, 2, do_idl_compound_index },
     { "help", NULL, 0, INT_MAX, do_help },
     { NULL, NULL, 0, 0, NULL },
 };
diff --git a/tests/test-skiplist.c b/tests/test-skiplist.c
new file mode 100644
index 0000000..36d9b8c
--- /dev/null
+++ b/tests/test-skiplist.c
@@ -0,0 +1,210 @@
+/* Copyright (C) 2016 Hewlett Packard Enterprise Development LP
+ * All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* A non-exhaustive test for some of the functions and macros declared in
+ * skiplist.h. */
+
+#include <config.h>
+#undef NDEBUG
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "ovstest.h"
+#include "skiplist.h"
+#include "random.h"
+#include "util.h"
+
+static void
+test_skiplist_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED);
+
+static int test_skiplist_cmp(const void *a, const void *b, const void *conf);
+
+static void test_skiplist_insert(void);
+static void test_skiplist_delete(void);
+static void test_skiplist_find(void);
+static void test_skiplist_forward_to(void);
+static void test_skiplist_random(void);
+
+static int test_skiplist_cmp(const void *a, const void *b, const void *conf OVS_UNUSED)
+{
+    const int *n = (const int *)a;
+    const int *m = (const int *)b;
+    return (*n > *m) - (*n < *m);
+}
+
+static void test_skiplist_insert(void)
+{
+    struct skiplist *sl = skiplist_create(14, test_skiplist_cmp, NULL);
+    skiplist_set_free_func(sl, free);
+    int i;
+    int *integer;
+    /* Insert a million rows */
+    for(i = 0; i < 1000000; i++){
+        integer = malloc(sizeof(int));
+        *integer = i;
+        skiplist_insert(sl, integer);
+    }
+
+    /* Check that the skiplist maintains the list sorted */
+    struct skiplist_node *node = skiplist_first(sl);
+
+    for(i = 0; i < 1000000; i++){
+        integer = (int*)skiplist_get_data(node);
+        assert(i == *integer);
+        node = skiplist_next(node);
+    }
+
+    skiplist_destroy(sl);
+}
+
+static void test_skiplist_delete(void)
+{
+    struct skiplist *sl = skiplist_create(3, test_skiplist_cmp, NULL);
+    int a, b, c;
+    a = 1;
+    b = 2;
+    c = 3;
+    /* Insert rows */
+    skiplist_insert(sl, &a);
+    skiplist_insert(sl, &c);
+    skiplist_insert(sl, &b);
+
+    /* Check that the items exists */
+    assert(a == *(int *)skiplist_get_data(skiplist_find(sl, &a)));
+    assert(b == *(int *)skiplist_get_data(skiplist_find(sl, &b)));
+    assert(c == *(int *)skiplist_get_data(skiplist_find(sl, &c)));
+
+    /* Delete b*/
+    skiplist_delete(sl, &b);
+
+    /* Check that the items doesn't exists */
+    assert(a == *(int *)skiplist_get_data(skiplist_find(sl, &a)));
+    assert(NULL == skiplist_get_data(skiplist_find(sl, &b)));
+    assert(c == *(int *)skiplist_get_data(skiplist_find(sl, &c)));
+
+    skiplist_destroy(sl);
+}
+
+static void test_skiplist_find(void)
+{
+    struct skiplist *sl = skiplist_create(14, test_skiplist_cmp, NULL);
+    skiplist_set_free_func(sl, free);
+
+    int i;
+    int *integer;
+    /* Insert a many rows */
+    for(i = 0; i < 1000000; i++){
+        integer = malloc(sizeof(int));
+        *integer = i;
+        skiplist_insert(sl, integer);
+    }
+
+    /* Seek all the items */
+    for(i = 0; i < 1000000; i++){
+        integer = (int*)skiplist_get_data(skiplist_find(sl, &i));
+        assert(i == *integer);
+    }
+
+    skiplist_destroy(sl);
+}
+
+static void test_skiplist_forward_to(void)
+{
+    struct skiplist *sl = skiplist_create(3, test_skiplist_cmp, NULL);
+    int a, b, c, d, x;
+    a = 1;
+    b = 3;
+    c = 7;
+    d = 10;
+    /* Insert rows */
+    skiplist_insert(sl, &a);
+    skiplist_insert(sl, &c);
+    skiplist_insert(sl, &b);
+    skiplist_insert(sl, &d);
+
+    /* Check that forward_to returns the expected value */
+    x = a;
+    assert(a == *(int *)skiplist_get_data(skiplist_forward_to(sl, &x)));
+
+    x = 2;
+    assert(b == *(int *)skiplist_get_data(skiplist_forward_to(sl, &x)));
+
+    x = 5;
+    assert(c == *(int *)skiplist_get_data(skiplist_forward_to(sl, &x)));
+
+    x = 8;
+    assert(d == *(int *)skiplist_get_data(skiplist_forward_to(sl, &x)));
+
+    x = 15;
+    assert(NULL == (int *)skiplist_get_data(skiplist_forward_to(sl, &x)));
+
+    /* Destroy skiplist */
+    skiplist_destroy(sl);
+}
+
+static void
+test_skiplist_random(void)
+{
+    int j;
+    for(j=1; j<64; j++) {
+        struct skiplist *sl = skiplist_create(j, test_skiplist_cmp, NULL);
+        int total_numbers = 50;
+        int expected_count = 0;
+        int *numbers = malloc(sizeof(int) * total_numbers);
+        int i, op, element;
+        for(i = 0; i < total_numbers; i++){
+            numbers[i] = i;
+        }
+        random_init();
+        for(i = 0; i < total_numbers*1000; i++){
+            op = random_uint32() % 2;
+            element = random_range(total_numbers);
+            if(op == 0){
+                if(!skiplist_find(sl, &numbers[element])) {
+                    expected_count++;
+                }
+                skiplist_insert(sl, &numbers[element]);
+            } else {
+                if(skiplist_find(sl, &numbers[element])) {
+                    expected_count--;
+                }
+                skiplist_delete(sl, &numbers[element]);
+            }
+            ovs_assert(expected_count == skiplist_get_size(sl));
+        }
+
+        skiplist_destroy(sl);
+        free(numbers);
+    }
+}
+
+static void
+test_skiplist_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+{
+    printf("skiplist insert\n");
+    test_skiplist_insert();
+    printf("skiplist delete\n");
+    test_skiplist_delete();
+    printf("skiplist find\n");
+    test_skiplist_find();
+    printf("skiplist forward_to\n");
+    test_skiplist_forward_to();
+    printf("skiplist random\n");
+	test_skiplist_random();
+    printf("\n");
+}
+
+OVSTEST_REGISTER("test-skiplist", test_skiplist_main);
-- 
1.9.1



More information about the dev mailing list