1/*
2 *
3 *  Copyright (C) 2006-2007  Peter Johnson
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include "util.h"
31#include "libyasm/errwarn.h"
32#include "libyasm/file.h"
33
34typedef struct Test_Entry {
35    /* input string */
36    const char *input;
37
38    /* input length */
39    size_t in_len;
40
41    /* correct output string */
42    const char *result;
43
44    /* correct output length */
45    size_t result_len;
46
47    /* expected warning, if any */
48    const char *warn;
49} Test_Entry;
50
51static Test_Entry tests[] = {
52    {"noescape", 8, "noescape", 8, NULL},
53    {"noescape2", 10, "noescape2", 10, NULL},   /* includes trailing zero */
54    {"\\\\\\b\\f\\n\\r\\t\\\"", 14, "\\\b\f\n\r\t\"", 7, NULL},
55    {"\\a", 2, "a", 1, NULL},
56    /* hex tests */
57    {"\\x", 2, "\x00", 1, NULL},
58    {"\\x12", 4, "\x12", 1, NULL},
59    {"\\x1234", 6, "\x34", 1, NULL},
60    {"\\xg", 3, "\x00g", 2, NULL},
61    {"\\xaga", 5, "\x0aga", 3, NULL},
62    {"\\xaag", 5, "\xaag", 2, NULL},
63    {"\\xaaa", 5, "\xaa", 1, NULL},
64    {"\\x55559", 7, "\x59", 1, NULL},
65
66    /* oct tests */
67    {"\\778", 4, "\000", 1, "octal value out of range"},
68    {"\\779", 4, "\001", 1, "octal value out of range"},
69    {"\\1x", 3, "\001x", 2, NULL},
70    {"\\7779", 5, "\xff" "9", 2, NULL},
71    {"\\7999", 5, "\x11" "9", 2, "octal value out of range"},
72    {"\\77a", 4, "\077a", 2, NULL},
73    {"\\5555555", 8, "\x6d" "5555", 5, NULL},
74    {"\\9999", 5, "\x91" "9", 2, "octal value out of range"},
75};
76
77static char failed[1000];
78static char failmsg[100];
79
80static int
81run_test(Test_Entry *test)
82{
83    char str[256];
84    size_t len;
85    yasm_warn_class wclass;
86    char *wstr;
87
88    strncpy(str, test->input, test->in_len);
89    len = test->in_len;
90
91    yasm_unescape_cstring((unsigned char *)str, &len);
92    if (len != test->result_len) {
93        sprintf(failmsg,
94                "unescape_cstring(\"%s\", %lu) bad output len: expected %lu, got %lu!",
95                test->input, (unsigned long)test->in_len,
96                (unsigned long)test->result_len, (unsigned long)len);
97        return 1;
98    }
99
100    if (strncmp(str, test->result, len) != 0) {
101        sprintf(failmsg,
102                "unescape_cstring(\"%s\", %lu) bad output: expected \"%s\", got \"%s\"!",
103                test->input, (unsigned long)test->in_len, test->result, str);
104        return 1;
105    }
106
107    yasm_warn_fetch(&wclass, &wstr);
108    if (wstr != NULL && test->warn == NULL) {
109        sprintf(failmsg,
110                "unescape_cstring(\"%s\", %lu) unexpected warning: %s!",
111                test->input, (unsigned long)test->in_len, wstr);
112        return 1;
113    }
114    if (wstr == NULL && test->warn != NULL) {
115        sprintf(failmsg,
116                "unescape_cstring(\"%s\", %lu) expected warning: %s, did not get it!",
117                test->input, (unsigned long)test->in_len, test->warn);
118        return 1;
119    }
120    if (wstr && test->warn && strcmp(wstr, test->warn) != 0) {
121        sprintf(failmsg,
122                "unescape_cstring(\"%s\", %lu) expected warning: %s, got %s!",
123                test->input, (unsigned long)test->in_len, test->warn, wstr);
124        return 1;
125    }
126    yasm_xfree(wstr);
127
128    return 0;
129}
130
131int
132main(void)
133{
134    int nf = 0;
135    int numtests = sizeof(tests)/sizeof(Test_Entry);
136    int i;
137
138    yasm_errwarn_initialize();
139
140    failed[0] = '\0';
141    printf("Test uncstring_test: ");
142    for (i=0; i<numtests; i++) {
143        int fail = run_test(&tests[i]);
144        printf("%c", fail>0 ? 'F':'.');
145        fflush(stdout);
146        if (fail)
147            sprintf(failed, "%s ** F: %s\n", failed, failmsg);
148        nf += fail;
149    }
150
151    printf(" +%d-%d/%d %d%%\n%s",
152           numtests-nf, nf, numtests, 100*(numtests-nf)/numtests, failed);
153
154    yasm_errwarn_cleanup();
155    return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
156}
157