summaryrefslogtreecommitdiff
path: root/common/tests/test-lexer.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/tests/test-lexer.c')
-rw-r--r--common/tests/test-lexer.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/common/tests/test-lexer.c b/common/tests/test-lexer.c
new file mode 100644
index 0000000..02ea5c5
--- /dev/null
+++ b/common/tests/test-lexer.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2013 Red Hat Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ * * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ * * The names of contributors to this software may not be
+ * used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#include "config.h"
+#include "CuTest.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "compat.h"
+#include "debug.h"
+#include "lexer.h"
+#include "library.h"
+#include "pem.h"
+
+typedef struct {
+ int tok_type;
+ const char *name;
+ const char *value;
+} expected_tok;
+
+static void
+on_pem_get_type (const char *type,
+ const unsigned char *contents,
+ size_t length,
+ void *user_data)
+{
+ char **result = (char **)user_data;
+ *result = strdup (type);
+}
+
+static void
+check_lex_msg (CuTest *tc,
+ const char *file,
+ int line,
+ const expected_tok *expected,
+ const char *input,
+ bool failure)
+{
+ unsigned int count;
+ p11_lexer lexer;
+ char *type;
+ bool failed;
+ int i;
+
+ p11_lexer_init (&lexer, "test", input, strlen (input));
+ for (i = 0; p11_lexer_next (&lexer, &failed); i++) {
+ CuAssertIntEquals_LineMsg (tc, file, line,
+ "lexer token type does not match",
+ expected[i].tok_type, lexer.tok_type);
+ switch (lexer.tok_type) {
+ case TOK_FIELD:
+ CuAssertStrEquals_LineMsg (tc, file, line,
+ "field name doesn't match",
+ expected[i].name, lexer.tok.field.name);
+ CuAssertStrEquals_LineMsg (tc, file, line,
+ "field value doesn't match",
+ expected[i].value, lexer.tok.field.value);
+ break;
+ case TOK_SECTION:
+ CuAssertStrEquals_LineMsg (tc, file, line,
+ "section name doesn't match",
+ expected[i].name, lexer.tok.field.name);
+ break;
+ case TOK_PEM:
+ type = NULL;
+ count = p11_pem_parse (lexer.tok.pem.begin, lexer.tok.pem.length,
+ on_pem_get_type, &type);
+ CuAssertIntEquals_LineMsg (tc, file, line,
+ "wrong number of PEM blocks",
+ 1, count);
+ CuAssertStrEquals_LineMsg (tc, file, line,
+ "wrong type of PEM block",
+ expected[i].name, type);
+ free (type);
+ break;
+ case TOK_EOF:
+ CuFail_Line (tc, file, line, NULL, "eof should not be recieved");
+ break;
+ }
+ }
+
+ if (failure)
+ CuAssert_Line (tc, file, line, "lexing didn't fail", failed);
+ else
+ CuAssert_Line (tc, file, line, "lexing failed", !failed);
+ CuAssertIntEquals_LineMsg (tc, file, line,
+ "premature end of lexing",
+ TOK_EOF, expected[i].tok_type);
+
+ p11_lexer_done (&lexer);
+}
+
+#define check_lex_success(tc, expected, input) \
+ check_lex_msg (tc, __FILE__, __LINE__, expected, input, false)
+
+#define check_lex_failure(tc, expected, input) \
+ check_lex_msg (tc, __FILE__, __LINE__, expected, input, true)
+
+static void
+test_basic (CuTest *tc)
+{
+ const char *input = "[the header]\n"
+ "field: value\n"
+ "-----BEGIN BLOCK1-----\n"
+ "aYNNXqshlVxCdo8QfKeXh3GUzd/yn4LYIVgQrx4a\n"
+ "-----END BLOCK1-----\n";
+
+ const expected_tok expected[] = {
+ { TOK_SECTION, "the header" },
+ { TOK_FIELD, "field", "value" },
+ { TOK_PEM, "BLOCK1", },
+ { TOK_EOF }
+ };
+
+ check_lex_success (tc, expected, input);
+}
+
+static void
+test_corners (CuTest *tc)
+{
+ const char *input = "\r\n" /* blankline */
+ " [the header]\r\n" /* bad line endings */
+ " field: value \r\n" /* whitespace */
+ "number: 2\n" /* extra space*/
+ "number :3\n" /* extra space*/
+ "number : 4\n" /* extra space*/
+ "\n"
+ " # A comment \n"
+ "not-a-comment: # value\n"
+ "-----BEGIN BLOCK1-----\r\n"
+ "aYNNXqshlVxCdo8QfKeXh3GUzd/yn4LYIVgQrx4a\r\n"
+ "-----END BLOCK1-----"; /* no new line */
+
+ const expected_tok expected[] = {
+ { TOK_SECTION, "the header" },
+ { TOK_FIELD, "field", "value" },
+ { TOK_FIELD, "number", "2" },
+ { TOK_FIELD, "number", "3" },
+ { TOK_FIELD, "number", "4" },
+ { TOK_FIELD, "not-a-comment", "# value" },
+ { TOK_PEM, "BLOCK1", },
+ { TOK_EOF }
+ };
+
+ check_lex_success (tc, expected, input);
+}
+
+static void
+test_following (CuTest *tc)
+{
+ const char *input = "-----BEGIN BLOCK1-----\n"
+ "aYNNXqshlVxCdo8QfKeXh3GUzd/yn4LYIVgQrx4a\n"
+ "-----END BLOCK1-----\n"
+ "field: value";
+
+ const expected_tok expected[] = {
+ { TOK_PEM, "BLOCK1", },
+ { TOK_FIELD, "field", "value" },
+ { TOK_EOF }
+ };
+
+ check_lex_success (tc, expected, input);
+}
+
+static void
+test_bad_pem (CuTest *tc)
+{
+ const char *input = "field: value\n"
+ "-----BEGIN BLOCK1-----\n"
+ "aYNNXqshlVxCdo8QfKeXh3GUzd/yn4LYIVgQrx4a\n";
+
+ const expected_tok expected[] = {
+ { TOK_FIELD, "field", "value" },
+ { TOK_EOF }
+ };
+
+ p11_message_quiet ();
+
+ check_lex_failure (tc, expected, input);
+
+ p11_message_loud ();
+}
+
+static void
+test_bad_section (CuTest *tc)
+{
+ const char *input = "field: value\n"
+ "[section\n"
+ "bad]\n";
+
+ const expected_tok expected[] = {
+ { TOK_FIELD, "field", "value" },
+ { TOK_EOF }
+ };
+
+ p11_message_quiet ();
+
+ check_lex_failure (tc, expected, input);
+
+ p11_message_loud ();
+}
+
+static void
+test_bad_value (CuTest *tc)
+{
+ const char *input = "field_value\n"
+ "[section\n"
+ "bad]\n";
+
+ const expected_tok expected[] = {
+ { TOK_EOF }
+ };
+
+ p11_message_quiet ();
+
+ check_lex_failure (tc, expected, input);
+
+ p11_message_loud ();
+}
+
+int
+main (void)
+{
+ CuString *output = CuStringNew ();
+ CuSuite* suite = CuSuiteNew ();
+ int ret;
+
+ putenv ("P11_KIT_STRICT=1");
+ p11_debug_init ();
+ p11_library_init ();
+
+ SUITE_ADD_TEST (suite, test_basic);
+ SUITE_ADD_TEST (suite, test_corners);
+ SUITE_ADD_TEST (suite, test_following);
+ SUITE_ADD_TEST (suite, test_bad_pem);
+ SUITE_ADD_TEST (suite, test_bad_section);
+ SUITE_ADD_TEST (suite, test_bad_value);
+
+ CuSuiteRun (suite);
+ CuSuiteSummary (suite, output);
+ CuSuiteDetails (suite, output);
+ printf ("%s\n", output->buffer);
+ ret = suite->failCount;
+ CuSuiteDelete (suite);
+ CuStringDelete (output);
+
+ return ret;
+}