1/*
2 *
3 *  Copyright (C) 2005-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 "libyasm/intnum.c"
31
32typedef struct Test_Entry {
33    /* signedness (0=unsigned, 1=signed) */
34    int sign;
35
36    /* whether input value should be negated */
37    int negate;
38
39    /* input value (as hex string) */
40    const char *input;
41
42    /* correct size returned from both size_leb128 and get_leb128 */
43    unsigned long outsize;
44
45    /* correct return data from get_leb128 */
46    const unsigned char *result;
47} Test_Entry;
48
49static Test_Entry tests[] = {
50    /* Unsigned values */
51    {0, 0, "0", 1, (const unsigned char *)"\x00"},
52    {0, 0, "2", 1, (const unsigned char *)"\x02"},
53    {0, 0, "7F", 1, (const unsigned char *)"\x7F"},
54    {0, 0, "80", 2, (const unsigned char *)"\x80\x01"},
55    {0, 0, "81", 2, (const unsigned char *)"\x81\x01"},
56    {0, 0, "82", 2, (const unsigned char *)"\x82\x01"},
57    {0, 0, "3239", 2, (const unsigned char *)"\xB9\x64"},
58    /* Signed zero value */
59    {1, 0, "0", 1, (const unsigned char *)"\x00"},
60    /* Signed positive values */
61    {1, 0, "2", 1, (const unsigned char *)"\x02"},
62    {1, 0, "7F", 2, (const unsigned char *)"\xFF\x00"},
63    {1, 0, "80", 2, (const unsigned char *)"\x80\x01"},
64    {1, 0, "81", 2, (const unsigned char *)"\x81\x01"},
65    /* Signed negative values */
66    {1, 1, "2", 1, (const unsigned char *)"\x7E"},
67    {1, 1, "7F", 2, (const unsigned char *)"\x81\x7F"},
68    {1, 1, "80", 2, (const unsigned char *)"\x80\x7F"},
69    {1, 1, "81", 2, (const unsigned char *)"\xFF\x7E"},
70};
71
72static char failed[1000];
73static char failmsg[100];
74
75static int
76run_output_test(Test_Entry *test)
77{
78    char *valstr = yasm__xstrdup(test->input);
79    yasm_intnum *intn = yasm_intnum_create_hex(valstr);
80    unsigned long size, i;
81    unsigned char out[100];
82    int bad;
83
84    yasm_xfree(valstr);
85
86    if (test->negate)
87        yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
88
89    size = yasm_intnum_size_leb128(intn, test->sign);
90    if (size != test->outsize) {
91        yasm_intnum_destroy(intn);
92        sprintf(failmsg, "%ssigned %s%s size() bad size: expected %lu, got %lu!",
93                test->sign?"":"un", test->negate?"-":"", test->input,
94                test->outsize, size);
95        return 1;
96    }
97
98    for (i=0; i<sizeof(out); i++)
99        out[i] = 0xFF;
100    size = yasm_intnum_get_leb128(intn, out, test->sign);
101    if (size != test->outsize) {
102        yasm_intnum_destroy(intn);
103        sprintf(failmsg, "%ssigned %s%s get() bad size: expected %lu, got %lu!",
104                test->sign?"":"un", test->negate?"-":"", test->input,
105                test->outsize, size);
106        return 1;
107    }
108
109    bad = 0;
110    for (i=0; i<test->outsize && !bad; i++) {
111        if (out[i] != test->result[i])
112            bad = 1;
113    }
114    if (bad) {
115        yasm_intnum_destroy(intn);
116        sprintf(failmsg, "%ssigned %s%s get() bad output!",
117                test->sign?"":"un", test->negate?"-":"", test->input);
118        return 1;
119    }
120
121    yasm_intnum_destroy(intn);
122    return 0;
123}
124
125static int
126run_input_test(Test_Entry *test)
127{
128    char *valstr = yasm__xstrdup(test->input);
129    yasm_intnum *intn = yasm_intnum_create_hex(valstr);
130    yasm_intnum *testn;
131    unsigned long size;
132
133    yasm_xfree(valstr);
134
135    if (test->negate)
136        yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
137
138    testn = yasm_intnum_create_leb128(test->result, test->sign, &size);
139    if (size != test->outsize) {
140        yasm_intnum_destroy(testn);
141        yasm_intnum_destroy(intn);
142        sprintf(failmsg, "%ssigned %s%s create() bad size: expected %lu, got %lu!",
143                test->sign?"":"un", test->negate?"-":"", test->input,
144                test->outsize, size);
145        return 1;
146    }
147
148    yasm_intnum_calc(intn, YASM_EXPR_EQ, testn);
149    if (!yasm_intnum_is_pos1(intn)) {
150        yasm_intnum_destroy(testn);
151        yasm_intnum_destroy(intn);
152        sprintf(failmsg, "%ssigned %s%s create() bad output!",
153                test->sign?"":"un", test->negate?"-":"", test->input);
154        return 1;
155    }
156
157    yasm_intnum_destroy(testn);
158    yasm_intnum_destroy(intn);
159    return 0;
160}
161
162int
163main(void)
164{
165    int nf = 0;
166    int numtests = sizeof(tests)/sizeof(Test_Entry);
167    int i;
168
169    if (BitVector_Boot() != ErrCode_Ok)
170        return EXIT_FAILURE;
171    yasm_intnum_initialize();
172
173    failed[0] = '\0';
174    printf("Test leb128_test: ");
175    for (i=0; i<numtests; i++) {
176        int fail;
177
178        fail = run_output_test(&tests[i]);
179        printf("%c", fail>0 ? 'F':'.');
180        fflush(stdout);
181        if (fail)
182            sprintf(failed, "%s ** F: %s\n", failed, failmsg);
183        nf += fail;
184
185        fail = run_input_test(&tests[i]);
186        printf("%c", fail>0 ? 'F':'.');
187        fflush(stdout);
188        if (fail)
189            sprintf(failed, "%s ** F: %s\n", failed, failmsg);
190        nf += fail;
191    }
192
193    yasm_intnum_cleanup();
194
195    printf(" +%d-%d/%d %d%%\n%s",
196           numtests*2-nf, nf, numtests*2, 100*(numtests*2-nf)/(numtests*2),
197           failed);
198    return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
199}
200