lex: New lexical analyzer module for use in OVN.
[cascardo/ovs.git] / tests / test-ovn.c
diff --git a/tests/test-ovn.c b/tests/test-ovn.c
new file mode 100644 (file)
index 0000000..b2f1838
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015 Nicira, Inc.
+ *
+ * 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.
+ */
+
+#include <config.h>
+#include "command-line.h"
+#include <getopt.h>
+#include "dynamic-string.h"
+#include "fatal-signal.h"
+#include "match.h"
+#include "ovn/lib/lex.h"
+#include "ovstest.h"
+#include "util.h"
+#include "openvswitch/vlog.h"
+
+static void
+compare_token(const struct lex_token *a, const struct lex_token *b)
+{
+    if (a->type != b->type) {
+        fprintf(stderr, "type differs: %d -> %d\n", a->type, b->type);
+        return;
+    }
+
+    if (!((a->s && b->s && !strcmp(a->s, b->s))
+          || (!a->s && !b->s))) {
+        fprintf(stderr, "string differs: %s -> %s\n",
+                a->s ? a->s : "(null)",
+                b->s ? b->s : "(null)");
+        return;
+    }
+
+    if (a->type == LEX_T_INTEGER || a->type == LEX_T_MASKED_INTEGER) {
+        if (memcmp(&a->value, &b->value, sizeof a->value)) {
+            fprintf(stderr, "value differs\n");
+            return;
+        }
+
+        if (a->type == LEX_T_MASKED_INTEGER
+            && memcmp(&a->mask, &b->mask, sizeof a->mask)) {
+            fprintf(stderr, "mask differs\n");
+            return;
+        }
+
+        if (a->format != b->format
+            && !(a->format == LEX_F_HEXADECIMAL
+                 && b->format == LEX_F_DECIMAL
+                 && a->value.integer == 0)) {
+            fprintf(stderr, "format differs: %d -> %d\n",
+                    a->format, b->format);
+        }
+    }
+}
+
+static void
+test_lex(struct ovs_cmdl_context *ctx OVS_UNUSED)
+{
+    struct ds input;
+    struct ds output;
+
+    ds_init(&input);
+    ds_init(&output);
+    while (!ds_get_line(&input, stdin)) {
+        struct lexer lexer;
+
+        lexer_init(&lexer, ds_cstr(&input));
+        ds_clear(&output);
+        while (lexer_get(&lexer) != LEX_T_END) {
+            size_t len = output.length;
+            lex_token_format(&lexer.token, &output);
+
+            /* Check that the formatted version can really be parsed back
+             * losslessly. */
+            if (lexer.token.type != LEX_T_ERROR) {
+                const char *s = ds_cstr(&output) + len;
+                struct lexer l2;
+
+                lexer_init(&l2, s);
+                lexer_get(&l2);
+                compare_token(&lexer.token, &l2.token);
+                lexer_destroy(&l2);
+            }
+            ds_put_char(&output, ' ');
+        }
+        lexer_destroy(&lexer);
+
+        ds_chomp(&output, ' ');
+        puts(ds_cstr(&output));
+    }
+    ds_destroy(&input);
+    ds_destroy(&output);
+}
+
+static void
+test_ovn_main(int argc, char *argv[])
+{
+    set_program_name(argv[0]);
+
+    static const struct ovs_cmdl_command commands[] = {
+        {"lex", NULL, 0, 0, test_lex},
+        {NULL, NULL, 0, 0, NULL},
+    };
+    struct ovs_cmdl_context ctx;
+    ctx.argc = argc - optind;
+    ctx.argv = argv + optind;
+    ovs_cmdl_run_command(&ctx, commands);
+}
+
+OVSTEST_REGISTER("test-ovn", test_ovn_main);