root / trunk / tests / YTS.c.erb

Revision 314, 8.2 kB (checked in by indeyets, 7 months ago)

moved check to erb file and regenerated test

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1//
2// YTS.c
3//
4// $Author$
5// $Date$
6//
7// Copyright (C) 2004 why the lucky stiff
8//
9// Well, this is the Yaml Testing Suite in the form of a plain C
10// API.  Basically, this is as good as C integration gets for Syck.
11// You've got to have a symbol table around.  From there, you can
12// query your data.
13//
14
15#include <string.h>
16#include "syck.h"
17#include "CuTest.h"
18
19/* YAML test node structures */
20#define T_STR 10
21#define T_SEQ 20
22#define T_MAP 30
23#define T_END 40
24#define ILEN  2
25
26struct test_node {
27    int type;
28    char *tag;
29    char *key;
30    struct test_node *value;
31};
32struct test_node end_node = { T_END };
33
34/*
35 * Assertion which compares a YAML document with an
36 * equivalent set of test_node structs.
37 */
38SYMID
39syck_copy_handler(p, n)
40    SyckParser *p;
41    SyckNode *n;
42{
43    int i = 0;
44    struct test_node *tn = S_ALLOC_N( struct test_node, 1 );
45
46    switch ( n->kind )
47    {
48        case syck_str_kind:
49            tn->type = T_STR;
50            tn->key = syck_strndup( n->data.str->ptr, n->data.str->len );
51            tn->value = 0;
52        break;
53
54        case syck_seq_kind:
55        {
56            struct test_node *val;
57            struct test_node *seq = S_ALLOC_N( struct test_node, n->data.list->idx + 1 );
58            tn->type = T_SEQ;
59            tn->key = 0;
60            for ( i = 0; i < n->data.list->idx; i++ )
61            {
62                SYMID oid = syck_seq_read( n, i );
63                syck_lookup_sym( p, oid, (char **)&val );
64                seq[i] = val[0];
65            }
66            seq[n->data.list->idx] = end_node;
67            tn->value = seq;
68        }
69        break;
70
71        case syck_map_kind:
72        {
73            struct test_node *val;
74            struct test_node *map = S_ALLOC_N( struct test_node, ( n->data.pairs->idx * 2 ) + 1 );
75            tn->type = T_MAP;
76            tn->key = 0;
77            for ( i = 0; i < n->data.pairs->idx; i++ )
78            {
79                SYMID oid = syck_map_read( n, map_key, i );
80                syck_lookup_sym( p, oid, (char **)&val );
81                map[i * 2] = val[0];
82
83                oid = syck_map_read( n, map_value, i );
84                syck_lookup_sym( p, oid, (char **)&val );
85                map[(i * 2) + 1] = val[0];
86            }
87            map[n->data.pairs->idx * 2] = end_node;
88            tn->value = map;
89        }
90        break;
91    }
92
93    tn->tag = 0;
94    if ( n->type_id != NULL ) {
95        tn->tag = syck_strndup( n->type_id, strlen( n->type_id ) );
96    }
97
98    return syck_add_sym( p, (char *) tn );
99}
100
101int
102syck_free_copies( char *key, struct test_node *tn, char *arg )
103{
104    if ( tn != NULL ) {
105        switch ( tn->type ) {
106            case T_STR:
107                S_FREE( tn->key );
108            break;
109
110            case T_SEQ:
111            case T_MAP:
112                S_FREE( tn->value );
113            break;
114        }
115        if ( tn->tag != NULL ) S_FREE( tn->tag );
116        S_FREE( tn );
117    }
118    tn = NULL;
119    return ST_CONTINUE;
120}
121
122void CuStreamCompareX( CuTest* tc, struct test_node *s1, struct test_node *s2 ) {
123    int i = 0;
124    while ( 1 ) {
125        CuAssertIntEquals( tc, s1[i].type, s2[i].type );
126        if ( s1[i].type == T_END ) return;
127        if ( s1[i].tag != 0 && s2[i].tag != 0 ) CuAssertStrEquals( tc, s1[i].tag, s2[i].tag );
128        switch ( s1[i].type ) {
129            case T_STR:
130                CuAssertStrEquals( tc, s1[i].key, s2[i].key );
131            break;
132            case T_SEQ:
133            case T_MAP:
134                CuStreamCompareX( tc, s1[i].value, s2[i].value );
135            break;
136        }
137        i++;
138    }
139}
140
141void CuStreamCompare( CuTest* tc, char *yaml, struct test_node *stream ) {
142    int doc_ct = 0;
143    struct test_node *ystream = S_ALLOC_N( struct test_node, doc_ct + 1 );
144
145    /* Set up parser */
146    SyckParser *parser = syck_new_parser();
147    syck_parser_str_auto( parser, yaml, NULL );
148    syck_parser_handler( parser, syck_copy_handler );
149    syck_parser_error_handler( parser, NULL );
150    syck_parser_implicit_typing( parser, 1 );
151    syck_parser_taguri_expansion( parser, 1 );
152
153    /* Parse all streams */
154    while ( 1 )
155    {
156        struct test_node *ydoc;
157        SYMID oid = syck_parse( parser );
158        if ( parser->eof == 1 ) break;
159
160        /* Add document to stream */
161        int res = syck_lookup_sym( parser, oid, (char **)&ydoc );
162        if (0 == res)
163            break;
164
165        ystream[doc_ct] = ydoc[0];
166        doc_ct++;
167        S_REALLOC_N( ystream, struct test_node, doc_ct + 1 );
168    }
169    ystream[doc_ct] = end_node;
170
171    /* Traverse the struct and the symbol table side-by-side */
172    /* DEBUG: y( stream, 0 ); y( ystream, 0 ); */
173    CuStreamCompareX( tc, stream, ystream );
174
175    /* Free the node tables and the parser */
176    S_FREE( ystream );
177    if ( parser->syms != NULL )
178        st_foreach( parser->syms, syck_free_copies, 0 );
179    syck_free_parser( parser );
180}
181
182/*
183 * Setup for testing N->Y->N.
184 */
185void
186test_output_handler( emitter, str, len )
187    SyckEmitter *emitter;
188    char *str;
189    long len;
190{
191    CuString *dest = (CuString *)emitter->bonus;
192    CuStringAppendLen( dest, str, len );
193}
194
195SYMID
196build_symbol_table( SyckEmitter *emitter, struct test_node *node ) {
197    switch ( node->type ) {
198        case T_SEQ:
199        case T_MAP:
200        {
201            int i = 0;
202            while ( node->value[i].type != T_END ) {
203                build_symbol_table( emitter, &node->value[i] );
204                i++;
205            }       
206        }
207        return syck_emitter_mark_node( emitter, (st_data_t)node );
208
209        default: break;
210    }
211    return 0;
212}
213
214void
215test_emitter_handler( SyckEmitter *emitter, st_data_t data ) {
216    struct test_node *node = (struct test_node *)data;
217    switch ( node->type ) {
218        case T_STR:
219            syck_emit_scalar( emitter, node->tag, scalar_none, 0, 0, 0, node->key, strlen( node->key ) );
220        break;
221        case T_SEQ:
222        {
223            int i = 0;
224            syck_emit_seq( emitter, node->tag, seq_none );
225            while ( node->value[i].type != T_END ) {
226                syck_emit_item( emitter, (st_data_t)&node->value[i] );
227                i++;
228            }       
229            syck_emit_end( emitter );
230        }
231        break;
232        case T_MAP:
233        {
234            int i = 0;
235            syck_emit_map( emitter, node->tag, map_none );
236            while ( node->value[i].type != T_END ) {
237                syck_emit_item( emitter, (st_data_t)&node->value[i] );
238                i++;
239            }       
240            syck_emit_end( emitter );
241        }
242        break;
243    }
244}
245
246void CuRoundTrip( CuTest* tc, struct test_node *stream ) {
247    int i = 0;
248    CuString *cs = CuStringNew();
249    SyckEmitter *emitter = syck_new_emitter();
250
251    /* Calculate anchors and tags */
252    build_symbol_table( emitter, stream );
253
254    /* Build the stream */
255    syck_output_handler( emitter, test_output_handler );
256    syck_emitter_handler( emitter, test_emitter_handler );
257    emitter->bonus = cs;
258    while ( stream[i].type != T_END )
259    {
260        syck_emit( emitter, (st_data_t)&stream[i] );
261        syck_emitter_flush( emitter, 0 );
262        i++;
263    }
264
265    /* Reload the stream and compare */
266    /* printf( "-- output for %s --\n%s\n--- end of output --\n", tc->name, cs->buffer ); */
267    CuStreamCompare( tc, cs->buffer, stream );
268    CuStringFree( cs );
269
270    syck_free_emitter( emitter );
271}
272
273/*
274 * ACTUAL TESTS FOR THE YAML TESTING SUITE BEGIN HERE
275 *   (EVERYTHING PREVIOUS WAS SET UP FOR THE TESTS)
276 */
277
278% syck_tests.each do |yt|
279/*
280 * Example <%= yt['spec'] %>: <%= yt['test'] %>
281 */
282void
283<%= yt['func'] %>( CuTest *tc )
284{
285<%= yt['syck'] %>
286
287    CuStreamCompare( tc,
288
289        /* YAML document */
290<%= yt['yaml'].gsub( /\\/, '\\\\\\\\' ).gsub( '"', '\"' ).gsub( "\t", "\\t" ).gsub( /^(.*)$/, '"\1\n"' ) %>
291        ,
292
293        /* C structure of validations */
294        stream
295    );
296
297    CuRoundTrip( tc, stream );
298}
299% end
300
301CuSuite *
302SyckGetSuite()
303{
304    CuSuite *suite = CuSuiteNew();
305% syck_tests.each do |yt|
306    SUITE_ADD_TEST( suite, <%= yt['func'] %> );
307% end
308    return suite;
309}
310
311int main(void)
312{
313        CuString *output = CuStringNew();
314        CuSuite* suite = SyckGetSuite();
315    int count;
316
317        CuSuiteRun(suite);
318        CuSuiteSummary(suite, output);
319        CuSuiteDetails(suite, output);
320
321        printf("%s\n", output->buffer);
322    count = suite->failCount;
323
324    CuStringFree( output );
325    CuSuiteFree( suite );
326
327    return count;
328}
Note: See TracBrowser for help on using the browser.