blob: fe7a41d1245aa5cf3c9557843d7bde056f733b5a [file] [log] [blame]
Rich Lanea06d0c32013-03-25 08:52:03 -07001# Copyright 2013, Big Switch Networks, Inc.
2#
3# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4# the following special exception:
5#
6# LOXI Exception
7#
8# As a special exception to the terms of the EPL, you may distribute libraries
9# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10# that copyright and licensing notices generated by LoxiGen are not altered or removed
11# from the LoxiGen Libraries and the notice provided below is (i) included in
12# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13# documentation for the LoxiGen Libraries, if distributed in binary form.
14#
15# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16#
17# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18# a copy of the EPL at:
19#
20# http://www.eclipse.org/legal/epl-v10.html
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25# EPL for the specific language governing permissions and limitations
26# under the EPL.
27
28"""
29@brief Test case generation functions
30
31@fixme Update the following
32The following components are generated.
33
34test_common.[ch]: A collection of common code for tests. Currently
35this includes the ability to set the scalar members of an object with
36incrementing values and then similarly verify those values
37
38test_scalar_acc.c: Instantiate each type of object, then set and get
39scalar values in the objects.
40
41test_list.c: Instantiate each type of list, add an element of each
42type the list supports, setting scalar values of the elements.
43
44test_match.c: Various tests for match objects
45
46test_msg.c: Instantiate top level messages
47
48These will move towards unified tests that do the following:
49
50Create or init an object.
51Populate the object with incrementing values.
52Possibly transform the object in some way (e.g., run the underlying
53wire buffer through a parse routine).
54Verify that the members all have the appropriate value
55
56Through out, checking the consistency of memory and memory operations
57is done with mcheck (not supported on Mac OS X).
58
59"""
60
61import sys
62import of_g
63import loxi_front_end.match as match
64import loxi_front_end.flags as flags
65from generic_utils import *
66import loxi_front_end.type_maps as type_maps
67import loxi_utils.loxi_utils as loxi_utils
68import loxi_front_end.identifiers as identifiers
69
70def var_name_map(m_type):
71 """
72 Map a type to a generic variable name for the type.
73 @param m_type The data type
74
75 Used mostly in test code generation, but also for the dup functions.
76 """
77 _var_name_map= dict(
78 uint8_t="val8",
79 uint16_t="val16",
80 uint32_t="val32",
81 uint64_t="val64",
82 of_port_no_t="port_no",
83 of_fm_cmd_t="fm_cmd",
84 of_wc_bmap_t="wc_bmap",
85 of_match_bmap_t = "match_bmap",
Andreas Wundsam53256162013-05-02 14:05:53 -070086 of_port_name_t="port_name",
Rich Lanea06d0c32013-03-25 08:52:03 -070087 of_table_name_t="table_name",
88 of_desc_str_t="desc_str",
Andreas Wundsam53256162013-05-02 14:05:53 -070089 of_serial_num_t="ser_num",
90 of_mac_addr_t="mac_addr",
Rich Lanea06d0c32013-03-25 08:52:03 -070091 of_ipv6_t="ipv6",
92 # Non-scalars; more TBD
93 of_octets_t="octets",
94 of_meter_features_t="features",
Dan Talaycoc0e802e2013-05-18 23:52:39 -070095 of_match_t="match",
96 # BSN extensions
97 of_bsn_vport_q_in_q_t="vport",
98 )
Rich Lanea06d0c32013-03-25 08:52:03 -070099
100 if m_type.find("of_list_") == 0:
101 return "list"
102 if m_type in of_g.of_mixed_types:
103 return of_g.of_mixed_types[m_type]["short_name"]
104 return _var_name_map[m_type]
105
106integer_types = ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
107 "of_port_no_t", "of_fm_cmd_t", "of_wc_bmap_t",
108 "of_match_bmap_t"]
109string_types = [ "of_port_name_t", "of_table_name_t",
Andreas Wundsam53256162013-05-02 14:05:53 -0700110 "of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
Rich Lanea06d0c32013-03-25 08:52:03 -0700111 "of_ipv6_t"]
112
113scalar_types = integer_types[:]
114scalar_types.extend(string_types)
115
116def ignore_member(cls, version, m_name, m_type):
117 """
118 Filter out names or types that either don't have accessors
119 or those that should not be messed with
120 or whose types we're not ready to deal with yet.
121 """
122 # This will probably need more granularity as more extensions are added
123 if (type_maps.class_is_extension(cls, version) and (
124 m_name == "experimenter" or
125 m_name == "subtype")):
126 return True
127 return loxi_utils.skip_member_name(m_name) or m_type not in scalar_types
128
129def gen_fill_string(out):
130 out.write("""
131
132/**
133 * The increment to use on values inside a string
134 */
135#define OF_TEST_STR_INCR 3
136
137/**
138 * Fill in a buffer with incrementing values starting
139 * at the given offset with the given value
140 * @param buf The buffer to fill
141 * @param value The value to use for data
142 * @param len The number of bytes to fill
143 */
144
145void
146of_test_str_fill(uint8_t *buf, int value, int len)
147{
148 int i;
149
150 for (i = 0; i < len; i++) {
151 *buf = value;
152 value += OF_TEST_STR_INCR;
153 buf++;
154 }
155}
156
157/**
158 * Given a buffer, verify that it's filled as above
159 * @param buf The buffer to check
160 * @param value The value to use for data
161 * @param len The number of bytes to fill
162 * @return Boolean True on equality (success)
163 */
164
165int
166of_test_str_check(uint8_t *buf, int value, int len)
167{
168 int i;
169 uint8_t val8;
170
171 val8 = value;
172
173 for (i = 0; i < len; i++) {
174 if (*buf != val8) {
175 return 0;
176 }
177 val8 += OF_TEST_STR_INCR;
178 buf++;
179 }
180
181 return 1;
182}
183
184/**
185 * Global that determines how octets should be populated
186 * -1 means use value % MAX (below) to determine length
187 * 0, 1, ... means used that fixed length
188 *
189 * Note: Was 16K, but that made objects too big. May add flexibility
190 * to call populate with a max parameter for length
191 */
192int octets_pop_style = -1;
193#define OCTETS_MAX_VALUE (128) /* 16K was too big */
194#define OCTETS_MULTIPLIER 6367 /* A prime */
195
196int
197of_octets_populate(of_octets_t *octets, int value)
198{
199 if (octets_pop_style < 0) {
200 octets->bytes = (value * OCTETS_MULTIPLIER) % OCTETS_MAX_VALUE;
201 } else {
202 octets->bytes = octets_pop_style;
203 }
204
205 if (octets->bytes != 0) {
206 if ((octets->data = (uint8_t *)MALLOC(octets->bytes)) == NULL) {
207 return 0;
208 }
209 of_test_str_fill(octets->data, value, octets->bytes);
210 value += 1;
211 }
212
213 return value;
214}
215
216int
217of_octets_check(of_octets_t *octets, int value)
218{
219 int len;
220
221 if (octets_pop_style < 0) {
222 len = (value * OCTETS_MULTIPLIER) % OCTETS_MAX_VALUE;
223 TEST_ASSERT(octets->bytes == len);
224 } else {
225 TEST_ASSERT(octets->bytes == octets_pop_style);
226 }
227
228 if (octets->bytes != 0) {
229 TEST_ASSERT(of_test_str_check(octets->data, value, octets->bytes)
230 == 1);
231 value += 1;
232 }
233
234 return value;
235}
236
237int
238of_match_populate(of_match_t *match, of_version_t version, int value)
239{
240 MEMSET(match, 0, sizeof(*match));
241 match->version = version;
242""")
243
244 for key, entry in match.of_match_members.items():
245 out.write("""
Andreas Wundsam53256162013-05-02 14:05:53 -0700246 if (!(of_match_incompat[version] &
Rich Lanea06d0c32013-03-25 08:52:03 -0700247 OF_OXM_BIT(OF_OXM_INDEX_%(ku)s))) {
248 OF_MATCH_MASK_%(ku)s_EXACT_SET(match);
249 VAR_%(u_type)s_INIT(match->fields.%(key)s, value);
250 value += 1;
251 }
252
253""" % dict(key=key, u_type=entry["m_type"].upper(), ku=key.upper()))
254
255 out.write("""
256 if (value % 2) {
257 /* Sometimes set ipv4 addr masks to non-exact */
258 match->masks.ipv4_src = 0xffff0000;
259 match->masks.ipv4_dst = 0xfffff800;
260 }
261 return value;
262}
263
264int
265of_match_check(of_match_t *match, of_version_t version, int value)
266{
267 of_match_t check;
268
269 value = of_match_populate(&check, match->version, value);
270 TEST_ASSERT(value != 0);
271 TEST_ASSERT(MEMCMP(match, &check, sizeof(check)) == 0);
272
273 return value;
274}
275""")
276
277def gen_common_test_header(out, name):
278 loxi_utils.gen_c_copy_license(out)
279 out.write("""
280/*
281 * Test header file
282 *
283 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
284 */
285
286#if !defined(_TEST_COMMON_H_)
287#define _TEST_COMMON_H_
288
289#define DISABLE_WARN_UNUSED_RESULT
290#include <loci/loci.h>
291#include <locitest/of_dup.h>
292#include <locitest/unittest.h>
293
294extern int global_error;
295extern int exit_on_error;
296
297/* @todo Make option for -k to continue tests if errors */
298#define RUN_TEST(test) do { \\
299 int rv; \\
300 TESTCASE(test, rv); \\
301 if (rv != TEST_PASS) { \\
302 global_error=1; \\
303 if (exit_on_error) return(1); \\
304 } \\
305 } while(0)
306
307#define TEST_OK(op) TEST_ASSERT((op) == OF_ERROR_NONE)
308#define TEST_INDIGO_OK(op) TEST_ASSERT((op) == INDIGO_ERROR_NONE)
309
310/*
311 * Declarations of functions to populate scalar values in a a class
312 */
313
314extern void of_test_str_fill(uint8_t *buf, int value, int len);
315extern int of_test_str_check(uint8_t *buf, int value, int len);
316
317
318extern int of_octets_populate(of_octets_t *octets, int value);
319extern int of_octets_check(of_octets_t *octets, int value);
320extern int of_match_populate(of_match_t *match, of_version_t version,
321 int value);
322extern int of_match_check(of_match_t *match, of_version_t version, int value);
323extern int test_ident_macros(void);
324extern int test_dump_objs(void);
325
326/* In test_match_utils.c */
327extern int test_match_utils(void);
328
329extern int run_unified_accessor_tests(void);
330extern int run_match_tests(void);
331extern int run_utility_tests(void);
332
333extern int run_scalar_acc_tests(void);
334extern int run_list_tests(void);
335extern int run_message_tests(void);
336extern int run_setup_from_add_tests(void);
337
338extern int run_validator_tests(void);
339
340extern int run_list_limits_tests(void);
341
342extern int test_ext_objs(void);
343
344""")
345
346 for version in of_g.of_version_range:
347 for cls in of_g.standard_class_order:
348 if not loxi_utils.class_in_version(cls, version):
349 continue
350 if cls in type_maps.inheritance_map:
351 continue
352 out.write("""
353extern int %(cls)s_%(v_name)s_populate(
354 %(cls)s_t *obj, int value);
355extern int %(cls)s_%(v_name)s_check(
356 %(cls)s_t *obj, int value);
357extern int %(cls)s_%(v_name)s_populate_scalars(
358 %(cls)s_t *obj, int value);
359extern int %(cls)s_%(v_name)s_check_scalars(
360 %(cls)s_t *obj, int value);
361""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
362
363 out.write("""
364/*
365 * Declarations for list population and check primitives
366 */
367""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700368
Rich Lanea06d0c32013-03-25 08:52:03 -0700369 for version in of_g.of_version_range:
370 for cls in of_g.ordered_list_objects:
371 if cls in type_maps.inheritance_map:
372 continue
373
374 if version in of_g.unified[cls]:
375 out.write("""
376extern int
377 list_setup_%(cls)s_%(v_name)s(
378 %(cls)s_t *list, int value);
379extern int
380 list_check_%(cls)s_%(v_name)s(
381 %(cls)s_t *list, int value);
382""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
383
384 out.write("\n#endif /* _TEST_COMMON_H_ */\n")
385
386def gen_common_test(out, name):
387 """
388 Generate common test content including main
389 """
390 loxi_utils.gen_c_copy_license(out)
391 out.write("""
392/*
393 * Common test code for LOCI
394 *
395 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
396 */
397
398#define DISABLE_WARN_UNUSED_RESULT
399#include "loci_log.h"
400#include <loci/loci_obj_dump.h>
401#include <locitest/unittest.h>
402#include <locitest/test_common.h>
403
404#if !defined(__APPLE__)
405#include <mcheck.h>
406#define MCHECK_INIT mcheck(NULL)
407#else /* mcheck not available under OS X */
408#define MCHECK_INIT do { } while (0)
409#endif
410
411/**
412 * Exit on error if set to 1
413 */
414int exit_on_error = 1;
415
416/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700417 * Global error state: 0 is okay, 1 is error
Rich Lanea06d0c32013-03-25 08:52:03 -0700418 */
419int global_error = 0;
420
421extern int run_unified_accessor_tests(void);
422extern int run_match_tests(void);
423extern int run_utility_tests(void);
424
425extern int run_scalar_acc_tests(void);
426extern int run_list_tests(void);
427extern int run_message_tests(void);
428
429/**
430 * Macros for initializing and checking scalar types
431 *
432 * @param var The variable being initialized or checked
433 * @param val The integer value to set/check against, see below
434 *
435 * Note that equality means something special for strings. Each byte
436 * is initialized to an incrementing value. So check is done against that.
437 *
438 */
439
440""")
441 for t in scalar_types:
442 if t in integer_types:
443 out.write("""
444#define VAR_%s_INIT(var, val) var = (%s)(val)
445#define VAR_%s_CHECK(var, val) ((var) == (%s)(val))
446""" % (t.upper(), t, t.upper(), t))
447 else:
448 out.write("""
449#define VAR_%s_INIT(var, val) \\
450 of_test_str_fill((uint8_t *)&(var), val, sizeof(var))
451#define VAR_%s_CHECK(var, val) \\
452 of_test_str_check((uint8_t *)&(var), val, sizeof(var))
453""" % (t.upper(), t.upper()))
454
455 gen_fill_string(out)
456 gen_scalar_set_check_funs(out)
457 gen_list_set_check_funs(out)
458 gen_unified_accessor_funs(out)
459
460 gen_ident_tests(out)
461 gen_log_test(out)
462
463def gen_message_scalar_test(out, name):
464 """
465 Generate test cases for message objects, scalar accessors
466 """
467
468 loxi_utils.gen_c_copy_license(out)
469 out.write("""
470/**
471 *
472 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
473 *
474 * Message-scalar tests for all versions
475 */
476
477#include <locitest/test_common.h>
478""")
479 for version in of_g.of_version_range:
480 v_name = loxi_utils.version_to_name(version)
481 out.write("""
482/**
483 * Message-scalar tests for version %s
484 */
485""" % v_name)
486 for cls in of_g.standard_class_order:
487 if cls in type_maps.inheritance_map:
488 continue
489 if version in of_g.unified[cls]:
490 message_scalar_test(out, version, cls)
491
492 out.write("""
493int
494run_scalar_acc_tests(void)
495{
496""")
497 for version in of_g.of_version_range:
498 v_name = loxi_utils.version_to_name(version)
499 for cls in of_g.standard_class_order:
500 if cls in type_maps.inheritance_map:
501 continue
502 if version in of_g.unified[cls]:
503 test_name = "%s_%s" % (cls, v_name)
504 out.write(" RUN_TEST(%s_scalar);\n" % test_name)
505
506 out.write(" return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -0700507
Rich Lanea06d0c32013-03-25 08:52:03 -0700508def message_scalar_test(out, version, cls):
509 """
510 Generate one test case for the given version and class
511 """
512
513 members, member_types = scalar_member_types_get(cls, version)
514 length = of_g.base_length[(cls, version)]
515 v_name = loxi_utils.version_to_name(version)
516
517 out.write("""
518static int
519test_%(cls)s_%(v_name)s_scalar(void)
520{
521 %(cls)s_t *obj;
522
523 obj = %(cls)s_new(%(v_name)s);
524 TEST_ASSERT(obj != NULL);
525 TEST_ASSERT(obj->version == %(v_name)s);
526 TEST_ASSERT(obj->length == %(length)d);
527 TEST_ASSERT(obj->parent == NULL);
528 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -0700529""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700530 v_name=v_name, length=length, version=version))
531 if not type_maps.class_is_virtual(cls):
532 out.write("""
533 if (obj->wire_length_get != NULL) {
534 int length;
535
536 obj->wire_length_get((of_object_t *)obj, &length);
537 TEST_ASSERT(length == %(length)d);
538 }
539
540 /* Set up incrementing values for scalar members */
541 %(cls)s_%(v_name)s_populate_scalars(obj, 1);
542
543 /* Check values just set */
544 TEST_ASSERT(%(cls)s_%(v_name)s_check_scalars(obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700545""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700546 v_name=v_name, length=length, version=version))
547
548 out.write("""
549 %(cls)s_delete(obj);
550
551 /* To do: Check memory */
552 return TEST_PASS;
553}
554""" % dict(cls=cls))
555
556# Get the members and list of scalar types for members of a given class
557def scalar_member_types_get(cls, version):
558 member_types = []
559
560 if not version in of_g.unified[cls]:
561 return ([], [])
562
563 if "use_version" in of_g.unified[cls][version]:
564 v = of_g.unified[cls][version]["use_version"]
565 members = of_g.unified[cls][v]["members"]
566 else:
567 members = of_g.unified[cls][version]["members"]
568 # Accumulate variables that are supported
569 for member in members:
570 m_type = member["m_type"]
571 m_name = member["name"]
Andreas Wundsam53256162013-05-02 14:05:53 -0700572 if (not loxi_utils.type_is_scalar(m_type) or
Rich Lanea06d0c32013-03-25 08:52:03 -0700573 ignore_member(cls, version, m_name, m_type)):
574 continue
575 if not m_type in member_types:
576 member_types.append(m_type)
577
578 return (members, member_types)
579
580def scalar_funs_instance(out, cls, version, members, member_types):
581 """
582 Generate one instance of scalar set/check functions
583 """
584 out.write("""
585/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700586 * Populate the scalar values in obj of type %(cls)s,
587 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700588 * @param obj Pointer to an object to populate
589 * @param value The seed value to use in populating the object
590 * @returns The value after increments for this object's values
591 */
592int %(cls)s_%(v_name)s_populate_scalars(
593 %(cls)s_t *obj, int value) {
594""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
595 # Declare string types
596 for t in member_types:
597 out.write(" %s %s;\n" % (t, var_name_map(t)))
598 for member in members:
599 m_type = member["m_type"]
600 m_name = member["name"]
601 if (not loxi_utils.type_is_scalar(m_type) or
602 ignore_member(cls, version, m_name, m_type)):
603 continue
604 v_name = var_name_map(m_type);
605 out.write("""
606 VAR_%(u_type)s_INIT(%(v_name)s, value);
607 %(cls)s_%(m_name)s_set(obj, %(v_name)s);
608 value += 1;
609""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
610 out.write("""
611 return value;
612}
613""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700614
Rich Lanea06d0c32013-03-25 08:52:03 -0700615 out.write("""
616/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700617 * Check scalar values in obj of type %(cls)s,
618 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700619 * @param obj Pointer to an object to check
620 * @param value Starting value for checking
621 * @returns The value after increments for this object's values
622 */
623int %(cls)s_%(v_name)s_check_scalars(
624 %(cls)s_t *obj, int value) {
625""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
626
627 for t in member_types:
628 out.write(" %s %s;\n" % (t, var_name_map(t)))
629 for member in members:
630 m_type = member["m_type"]
631 m_name = member["name"]
632 if (not loxi_utils.type_is_scalar(m_type) or
633 ignore_member(cls, version, m_name, m_type)):
634 continue
635 v_name = var_name_map(m_type);
636 out.write("""
637 %(cls)s_%(m_name)s_get(obj, &%(v_name)s);
638 TEST_ASSERT(VAR_%(u_type)s_CHECK(%(v_name)s, value));
639 value += 1;
640""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
641
642 out.write("""
643 return value;
644}
645
646""")
647
648def gen_scalar_set_check_funs(out):
649 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700650 For each object class with scalar members, generate functions that
Rich Lanea06d0c32013-03-25 08:52:03 -0700651 set and check their values
652 """
653 for version in of_g.of_version_range:
654 for cls in of_g.standard_class_order:
655 (members, member_types) = scalar_member_types_get(cls, version)
656 scalar_funs_instance(out, cls, version, members, member_types)
657
658
659# Helper function to set up a subclass instance for a test
660def setup_instance(out, cls, subcls, instance, v_name, inst_len, version):
661 base_type = loxi_utils.list_to_entry_type(cls)
662 setup_template = """
663 %(subcls)s_init(%(inst)s, %(v_name)s, -1, 1);
Andreas Wundsam53256162013-05-02 14:05:53 -0700664 %(cls)s_append_bind(list,
Rich Lanea06d0c32013-03-25 08:52:03 -0700665 (%(base_type)s_t *)%(inst)s);
666 value = %(subcls)s_%(v_name)s_populate(
667 %(inst)s, value);
668 cur_len += %(inst)s->length;
669 TEST_ASSERT(list->length == cur_len);
670"""
671 out.write("""
672 /* Append two instances of type %s */
673""" % subcls)
674 for i in range(2):
675 out.write(setup_template %
Andreas Wundsam53256162013-05-02 14:05:53 -0700676 dict(inst=instance, subcls=subcls, v_name=v_name,
677 base_type=base_type, cls=cls, inst_len=inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700678 version=version))
679
680def check_instance(out, cls, subcls, instance, v_name, inst_len, version, last):
681 check_template = ""
682 if inst_len >= 0:
683 check_template = """
684 TEST_ASSERT(%(inst)s->length == %(inst_len)d);
685 if (%(inst)s->wire_length_get != NULL) {
686 int length;
687
688 %(inst)s->wire_length_get(
689 (of_object_t *)&elt, &length);
690 TEST_ASSERT(length == %(inst_len)d);
691 }
692"""
693 check_template += """
694 TEST_ASSERT(%(inst)s->object_id == %(elt_name)s);
695 value = %(subcls)s_%(v_name)s_check(
696 %(inst)s, value);
697 TEST_ASSERT(value != 0);
698"""
699 out.write("\n /* Check two instances of type %s */" % instance)
700
Andreas Wundsam53256162013-05-02 14:05:53 -0700701 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700702 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
703 inst=instance, subcls=subcls,
704 v_name=loxi_utils.version_to_name(version)))
705 out.write("""\
706 TEST_OK(%(cls)s_next(list, &elt));
707""" % dict(cls=cls))
708
Andreas Wundsam53256162013-05-02 14:05:53 -0700709 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700710 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
711 inst=instance, subcls=subcls,
712 v_name=loxi_utils.version_to_name(version)))
713 if last:
714 out.write("""\
715 TEST_ASSERT(%(cls)s_next(list, &elt) == OF_ERROR_RANGE);
716""" % dict(cls=cls))
717 else:
718 out.write("""\
719 TEST_OK(%(cls)s_next(list, &elt));
720""" % dict(cls=cls))
721
722def setup_list_fn(out, version, cls):
723 """
724 Generate a helper function that populates a list with two
725 of each type of subclass it supports
726 """
727 out.write("""
728/**
729 * Set up a list of type %(cls)s with two of each type of subclass
730 */
731int
732list_setup_%(cls)s_%(v_name)s(
733 %(cls)s_t *list, int value)
734{
735""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
736 base_type = loxi_utils.list_to_entry_type(cls)
737 out.write("""
738 %(base_type)s_t elt;
739 int cur_len = 0;
740""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700741
Rich Lanea06d0c32013-03-25 08:52:03 -0700742 sub_classes = type_maps.sub_class_map(base_type, version)
743 v_name = loxi_utils.version_to_name(version)
744
745 if len(sub_classes) == 0:
746 out.write(" /* No subclasses for %s */\n"% base_type)
747 out.write(" %s_t *elt_p;\n" % base_type)
748 out.write("\n elt_p = &elt;\n")
749 else:
750 out.write(" /* Declare pointers for each subclass */\n")
751 for instance, subcls in sub_classes:
752 out.write(" %s_t *%s;\n" % (subcls, instance))
753 out.write("\n /* Instantiate pointers for each subclass */\n")
754 for instance, subcls in sub_classes:
755 out.write(" %s = &elt.%s;\n" % (instance, instance))
756
757 if len(sub_classes) == 0: # No inheritance case
758 inst_len = loxi_utils.base_type_to_length(base_type, version)
759 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
760 else:
761 for instance, subcls in sub_classes:
762 inst_len = of_g.base_length[(subcls, version)]
763 setup_instance(out, cls, subcls, instance, v_name, inst_len, version)
764 out.write("""
765
766 return value;
767}
768""")
769
770def check_list_fn(out, version, cls):
771 """
772 Generate a helper function that checks a list populated by above fn
773 """
774 out.write("""
775/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700776 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -0700777 * list_setup_%(cls)s_%(v_name)s
778 */
779int
780list_check_%(cls)s_%(v_name)s(
781 %(cls)s_t *list, int value)
782{
783""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
784 base_type = loxi_utils.list_to_entry_type(cls)
785 out.write("""
786 %(base_type)s_t elt;
787""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700788
Rich Lanea06d0c32013-03-25 08:52:03 -0700789 sub_classes = type_maps.sub_class_map(base_type, version)
790 v_name = loxi_utils.version_to_name(version)
791
792 if len(sub_classes) == 0:
793 out.write(" /* No subclasses for %s */\n"% base_type)
794 out.write(" %s_t *elt_p;\n" % base_type)
795 out.write("\n elt_p = &elt;\n")
796 else:
797 out.write(" /* Declare pointers for each subclass */\n")
798 for instance, subcls in sub_classes:
799 out.write(" %s_t *%s;\n" % (subcls, instance))
800 out.write("\n /* Instantiate pointers for each subclass */\n")
801 for instance, subcls in sub_classes:
802 out.write(" %s = &elt.%s;\n" % (instance, instance))
803
804 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
805 if len(sub_classes) == 0: # No inheritance case
806 if loxi_utils.class_is_var_len(base_type, version):
807 inst_len = -1
808 else:
809 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -0700810 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700811 version, True)
812 else:
813 count = 0
814 for instance, subcls in sub_classes:
815 count += 1
816 if loxi_utils.class_is_var_len(subcls, version):
817 inst_len = -1
818 else:
819 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -0700820 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700821 version, count==len(sub_classes))
822
823 out.write("""
824 return value;
825}
826""" % dict(base_type=base_type))
827
828def gen_list_set_check_funs(out):
829 for version in of_g.of_version_range:
830 for cls in of_g.ordered_list_objects:
831 if cls in type_maps.inheritance_map:
832 continue
833
834 if version in of_g.unified[cls]:
835 setup_list_fn(out, version, cls)
836 check_list_fn(out, version, cls)
837
838# Maybe: Get a map from list class to parent, mem_name of container
839
840def list_test(out, version, cls):
841 out.write("""
842static int
843test_%(cls)s_%(v_name)s(void)
844{
845""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
846 base_type = loxi_utils.list_to_entry_type(cls)
847
848 out.write(""" %(cls)s_t *list;
849 int value = 1;
850""" % dict(cls=cls, base_type=base_type))
851
852 out.write("""
853 list = %(cls)s_new(%(v_name)s);
854 TEST_ASSERT(list != NULL);
855 TEST_ASSERT(list->version == %(v_name)s);
856 TEST_ASSERT(list->length == 0);
857 TEST_ASSERT(list->parent == NULL);
858 TEST_ASSERT(list->object_id == %(enum_cls)s);
859
860 value = list_setup_%(cls)s_%(v_name)s(list, value);
861 TEST_ASSERT(value != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700862""" % dict(cls=cls, base_type=base_type, v_name=loxi_utils.version_to_name(version),
Rich Lanea06d0c32013-03-25 08:52:03 -0700863 enum_cls=loxi_utils.enum_name(cls)))
864
865 out.write("""
866 /* Now check values */
867 value = 1;
868 value = list_check_%(cls)s_%(v_name)s(list, value);
869 TEST_ASSERT(value != 0);
870""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
871
872 out.write("""
873 %(cls)s_delete(list);
874
875 return TEST_PASS;
876}
877""" % dict(cls=cls))
878
879def gen_list_test(out, name):
880 """
881 Generate base line test cases for lists
882 @param out The file handle to write to
883 """
884
885 loxi_utils.gen_c_copy_license(out)
886 out.write("""
887/**
888 *
889 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
890 *
891 * Message-scalar tests for all versions
892 */
893
894#include <locitest/test_common.h>
895""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700896
Rich Lanea06d0c32013-03-25 08:52:03 -0700897 for version in of_g.of_version_range:
898 v_name = loxi_utils.version_to_name(version)
899 out.write("""
900/**
901 * Baseline list tests for version %s
902 */
903""" % v_name)
904 for cls in of_g.ordered_list_objects:
905 if cls in type_maps.inheritance_map:
906 continue
907 if version in of_g.unified[cls]:
908 list_test(out, version, cls)
909
910 out.write("""
911int
912run_list_tests(void)
913{
914""")
915 for version in of_g.of_version_range:
916 v_name = loxi_utils.version_to_name(version)
917 for cls in of_g.ordered_list_objects:
918 if cls in type_maps.inheritance_map:
919 continue
920 if version in of_g.unified[cls]:
921 test_name = "%s_%s" % (cls, v_name)
922 out.write(" RUN_TEST(%s);\n" % test_name)
923
924 out.write("\n return TEST_PASS;\n}\n");
925
926def gen_match_test(out, name):
927 """
928 Generate baseline tests for match functions
929 """
930
931 loxi_utils.gen_c_copy_license(out)
932 out.write("""\
933/**
934 *
935 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
936 *
937 * Message-scalar tests for all versions
938 * @fixme These are mostly hard coded now.
939 */
940
941#include <locitest/test_common.h>
942
943static int
944test_match_1(void)
945{
946 of_match_v1_t *m_v1;
947 of_match_v2_t *m_v2;
948 of_match_v3_t *m_v3;
949 of_match_v4_t *m_v4;
950 of_match_t match;
951 int value = 1;
952 int idx;
953 uint32_t exp_value;
954
955 /* Verify default values for ip mask map */
956 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
957 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
958 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
959 if (idx < 32) {
960 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
961 }
962 }
963
964 TEST_ASSERT(of_ip_mask_map_set(17, 0xabcdef00) == OF_ERROR_NONE);
965 TEST_ASSERT(of_ip_mask_to_index(0xabcdef00) == 17);
966 TEST_ASSERT(of_ip_index_to_mask(17) == 0xabcdef00);
967
968 TEST_ASSERT(of_ip_mask_map_set(62, 0xabcdefff) == OF_ERROR_NONE);
969 TEST_ASSERT(of_ip_mask_to_index(0xabcdefff) == 62);
970 TEST_ASSERT(of_ip_index_to_mask(62) == 0xabcdefff);
971
972 /* Test re-init */
973 of_ip_mask_map_init();
974 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
975 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
976 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
977 if (idx < 32) {
978 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
979 }
980 }
981""")
982
983 for version in of_g.of_version_range:
984 out.write("""
985 /* Create/populate/convert and delete for version %(v_name)s */
986 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
987 TEST_ASSERT(m_v%(version)d != NULL);
988 TEST_ASSERT((value = of_match_populate(&match, %(v_name)s, value)) > 0);
989 TEST_OK(of_match_to_wire_match_v%(version)d(&match, m_v%(version)d));
990 of_match_v%(version)d_delete(m_v%(version)d);
991""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
992
993 out.write("""
994 return TEST_PASS;
995}
996""")
997
998 out.write("""
999static int
1000test_match_2(void)
1001{
1002 of_match_v1_t *m_v1;
1003 of_match_v2_t *m_v2;
1004 of_match_v3_t *m_v3;
1005 of_match_v3_t *m_v4;
1006 of_match_t match1;
1007 of_match_t match2;
1008 int value = 1;
1009""")
1010
1011 for version in of_g.of_version_range:
1012 out.write("""
1013 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
1014 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
1015 TEST_ASSERT(m_v%(version)d != NULL);
1016 TEST_OK(of_match_to_wire_match_v%(version)d(&match1, m_v%(version)d));
1017 TEST_OK(of_match_v%(version)d_to_match(m_v%(version)d, &match2));
1018 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1019 of_match_v%(version)d_delete(m_v%(version)d);
1020""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1021
1022 out.write("""
1023 return TEST_PASS;
1024}
1025""")
1026
1027 out.write("""
1028static int
1029test_match_3(void)
1030{
1031 of_match_t match1;
1032 of_match_t match2;
1033 int value = 1;
1034 of_octets_t octets;
1035""")
1036 for version in of_g.of_version_range:
1037 out.write("""
1038 /* Serialize to version %(v_name)s */
1039 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001040 TEST_ASSERT(of_match_serialize(%(v_name)s, &match1, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001041 OF_ERROR_NONE);
Andreas Wundsam53256162013-05-02 14:05:53 -07001042 TEST_ASSERT(of_match_deserialize(%(v_name)s, &match2, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001043 OF_ERROR_NONE);
1044 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1045 FREE(octets.data);
1046""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1047
1048 out.write("""
1049 return TEST_PASS;
1050}
1051""")
1052
1053 out.write("""
1054int run_match_tests(void)
1055{
1056 RUN_TEST(match_1);
1057 RUN_TEST(match_2);
1058 RUN_TEST(match_3);
1059 RUN_TEST(match_utils);
1060
1061 return TEST_PASS;
1062}
1063""")
1064
1065def gen_msg_test(out, name):
1066 loxi_utils.gen_c_copy_license(out)
1067 out.write("""
1068/**
1069 *
1070 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1071 *
1072 * Message-scalar tests for all versions
1073 */
1074
1075#include <locitest/test_common.h>
1076""")
1077 for version in of_g.of_version_range:
1078 for cls in of_g.ordered_messages:
1079 if not (cls, version) in of_g.base_length:
1080 continue
1081 bytes = of_g.base_length[(cls, version)]
1082 out.write("""
1083static int
1084test_%(cls)s_create_%(v_name)s(void)
1085{
1086 %(cls)s_t *obj;
1087 uint8_t *msg_buf;
1088 int value;
1089 int len;
1090
1091 obj = %(cls)s_new(%(v_name)s);
1092 TEST_ASSERT(obj != NULL);
1093 TEST_ASSERT(obj->version == %(v_name)s);
1094 TEST_ASSERT(obj->length == %(bytes)d);
1095 TEST_ASSERT(obj->parent == NULL);
1096 TEST_ASSERT(obj->object_id == %(enum)s);
1097
1098 /* Set up incrementing values for scalar members */
1099 value = %(cls)s_%(v_name)s_populate_scalars(obj, 1);
1100 TEST_ASSERT(value != 0);
1101
1102 /* Grab the underlying buffer from the message */
1103 len = obj->length;
1104 of_object_wire_buffer_steal((of_object_t *)obj, &msg_buf);
1105 TEST_ASSERT(msg_buf != NULL);
1106 %(cls)s_delete(obj);
1107 /* TODO: */
1108 TEST_ASSERT(of_message_to_object_id(msg_buf, len) == %(enum)s);
1109 obj = %(cls)s_new_from_message(OF_BUFFER_TO_MESSAGE(msg_buf));
1110
1111 TEST_ASSERT(obj != NULL);
1112
1113 /* @fixme Set up all message objects (recursively?) */
1114
1115 value = %(cls)s_%(v_name)s_check_scalars(obj, 1);
1116 TEST_ASSERT(value != 0);
1117
1118 %(cls)s_delete(obj);
1119
1120 return TEST_PASS;
1121}
1122""" % dict(cls=cls, version=version, enum=loxi_utils.enum_name(cls),
1123 v_name=loxi_utils.version_to_name(version), bytes=bytes))
1124
1125 out.write("""
1126int
1127run_message_tests(void)
1128{
1129""")
1130 for version in of_g.of_version_range:
1131 for cls in of_g.ordered_messages:
1132 if not (cls, version) in of_g.base_length:
1133 continue
1134 test_name = "%s_create_%s" % (cls, loxi_utils.version_to_name(version))
1135 out.write(" RUN_TEST(%s);\n" % test_name)
1136
1137 out.write("\n return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -07001138
Rich Lanea06d0c32013-03-25 08:52:03 -07001139
1140def gen_list_setup_check(out, cls, version):
1141 """
1142 Generate functions that populate and check a list with two
1143 of each type of subclass it supports
1144 """
1145 out.write("""
1146/**
1147 * Populate a list of type %(cls)s with two of each type of subclass
1148 * @param list Pointer to the list to be populated
1149 * @param value The seed value to use in populating the list
1150 * @returns The value after increments for this object's values
1151 */
1152int
1153%(cls)s_%(v_name)s_populate(
1154 %(cls)s_t *list, int value)
1155{
1156""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1157 base_type = loxi_utils.list_to_entry_type(cls)
1158 out.write("""
1159 %(base_type)s_t elt;
1160 int cur_len = 0;
1161""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001162
Rich Lanea06d0c32013-03-25 08:52:03 -07001163 sub_classes = type_maps.sub_class_map(base_type, version)
1164 v_name = loxi_utils.version_to_name(version)
1165
1166 if len(sub_classes) == 0:
1167 out.write(" /* No subclasses for %s */\n"% base_type)
1168 out.write(" %s_t *elt_p;\n" % base_type)
1169 out.write("\n elt_p = &elt;\n")
1170 else:
1171 out.write(" /* Declare pointers for each subclass */\n")
1172 for instance, subcls in sub_classes:
1173 out.write(" %s_t *%s;\n" % (subcls, instance))
1174 out.write("\n /* Instantiate pointers for each subclass */\n")
1175 for instance, subcls in sub_classes:
1176 out.write(" %s = &elt.%s;\n" % (instance, instance))
1177
1178# if type_maps.class_is_virtual(base_type):
1179# out.write("""\
1180# TEST_OK(%(base_type)s_header_init(
1181# (%(base_type)s_header_t *)&elt, %(v_name)s, -1, 1));
1182# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1183# else:
1184# out.write("""\
1185# TEST_OK(%(base_type)s_init(&elt, %(v_name)s, -1, 1));
1186# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1187
1188 if len(sub_classes) == 0: # No inheritance case
1189 inst_len = loxi_utils.base_type_to_length(base_type, version)
1190 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
1191 else:
1192 for instance, subcls in sub_classes:
1193 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001194 setup_instance(out, cls, subcls, instance, v_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001195 inst_len, version)
1196 out.write("""
1197 return value;
1198}
1199""")
1200 out.write("""
1201/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001202 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -07001203 * %(cls)s_%(v_name)s_populate
1204 * @param list Pointer to the list that was populated
1205 * @param value Starting value for checking
1206 * @returns The value after increments for this object's values
1207 */
1208int
1209%(cls)s_%(v_name)s_check(
1210 %(cls)s_t *list, int value)
1211{
1212""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1213 base_type = loxi_utils.list_to_entry_type(cls)
1214 out.write("""
1215 %(base_type)s_t elt;
1216 int count = 0;
1217 int rv;
1218""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001219
Rich Lanea06d0c32013-03-25 08:52:03 -07001220
1221 sub_classes = type_maps.sub_class_map(base_type, version)
1222 v_name = loxi_utils.version_to_name(version)
1223
1224 if len(sub_classes) == 0:
1225 entry_count = 2
1226 out.write(" /* No subclasses for %s */\n"% base_type)
1227 out.write(" %s_t *elt_p;\n" % base_type)
1228 out.write("\n elt_p = &elt;\n")
1229 else:
1230 entry_count = 2 * len(sub_classes) # Two of each type appended
1231 out.write(" /* Declare pointers for each subclass */\n")
1232 for instance, subcls in sub_classes:
1233 out.write(" %s_t *%s;\n" % (subcls, instance))
1234 out.write("\n /* Instantiate pointers for each subclass */\n")
1235 for instance, subcls in sub_classes:
1236 out.write(" %s = &elt.%s;\n" % (instance, instance))
1237
1238 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
1239 if len(sub_classes) == 0: # No inheritance case
1240 if loxi_utils.class_is_var_len(base_type, version):
1241 inst_len = -1
1242 else:
1243 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -07001244 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001245 version, True)
1246 else:
1247 count = 0
1248 for instance, subcls in sub_classes:
1249 count += 1
1250 if loxi_utils.class_is_var_len(subcls, version):
1251 inst_len = -1
1252 else:
1253 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001254 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001255 version, count==len(sub_classes))
1256 out.write("""
1257""" % dict(base_type=base_type))
1258
1259 out.write("""
1260 /* Do an iterate to test the iterator */
1261 %(u_cls)s_ITER(list, &elt, rv) {
1262 count += 1;
1263 }
1264
1265 TEST_ASSERT(rv == OF_ERROR_RANGE);
1266 TEST_ASSERT(count == %(entry_count)d);
1267
1268 /* We shoehorn a test of the dup functions here */
1269 {
1270 %(cls)s_t *dup;
1271
1272 TEST_ASSERT((dup = %(cls)s_dup(list)) != NULL);
1273 TEST_ASSERT(dup->length == list->length);
1274 TEST_ASSERT(dup->object_id == list->object_id);
1275 TEST_ASSERT(dup->version == list->version);
1276 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1277 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1278 of_object_delete((of_object_t *)dup);
1279
1280 /* And now for the generic dup function */
1281 TEST_ASSERT((dup = (%(cls)s_t *)
1282 of_object_dup(list)) != NULL);
1283 TEST_ASSERT(dup->length == list->length);
1284 TEST_ASSERT(dup->object_id == list->object_id);
1285 TEST_ASSERT(dup->version == list->version);
1286 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1287 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1288 of_object_delete((of_object_t *)dup);
1289 }
1290
1291 return value;
1292}
1293""" % dict(cls=cls, u_cls=cls.upper(), entry_count=entry_count))
1294
1295
1296def gen_class_setup_check(out, cls, version):
1297 out.write("""
1298/**
1299 * Populate all members of an object of type %(cls)s
1300 * with incrementing values
1301 * @param obj Pointer to an object to populate
1302 * @param value The seed value to use in populating the object
1303 * @returns The value after increments for this object's values
1304 */
1305
1306int
1307%(cls)s_%(v_name)s_populate(
1308 %(cls)s_t *obj, int value)
1309{
1310""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1311 members, member_types = loxi_utils.all_member_types_get(cls, version)
1312 for m_type in member_types:
1313 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1314 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1315 else:
1316 out.write(" %s *%s;\n" % (m_type, var_name_map(m_type)))
1317 out.write("""
1318 /* Run thru accessors after new to ensure okay */
1319""")
1320 for member in members:
1321 m_type = member["m_type"]
1322 m_name = member["name"]
1323 if loxi_utils.skip_member_name(m_name):
1324 continue
1325 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1326 out.write("""\
1327 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1328""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1329 else:
1330 sub_cls = m_type[:-2] # Trim _t
1331 out.write("""\
1332 {
1333 %(sub_cls)s_t sub_cls;
1334
1335 /* Test bind */
1336 %(cls)s_%(m_name)s_bind(obj, &sub_cls);
1337 }
Andreas Wundsam53256162013-05-02 14:05:53 -07001338""" % dict(var_name=var_name_map(m_type), cls=cls,
Rich Lanea06d0c32013-03-25 08:52:03 -07001339 m_name=m_name, sub_cls=sub_cls,
1340 v_name=loxi_utils.version_to_name(version)))
1341
1342 out.write("""
1343 value = %(cls)s_%(v_name)s_populate_scalars(
1344 obj, value);
1345 TEST_ASSERT(value != 0);
1346""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1347
1348 for member in members:
1349 m_type = member["m_type"]
1350 m_name = member["name"]
1351 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1352 continue
1353 if loxi_utils.skip_member_name(m_name):
1354 continue
1355 if m_type == "of_match_t":
1356 out.write("""\
1357 value = of_match_populate(&%(var_name)s, %(v_name)s, value);
1358 TEST_ASSERT(value != 0);
1359 %(cls)s_%(m_name)s_set(
1360 obj, &%(var_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001361""" % dict(cls=cls, var_name=var_name_map(m_type),
Rich Lanea06d0c32013-03-25 08:52:03 -07001362 m_name=m_name, v_name=loxi_utils.version_to_name(version)))
1363 elif m_type == "of_octets_t":
1364 out.write("""\
1365 value = of_octets_populate(&%(var_name)s, value);
1366 TEST_ASSERT(value != 0);
1367 %(cls)s_%(m_name)s_set(
1368 obj, &%(var_name)s);
1369 if (octets.bytes) {
1370 FREE(octets.data);
1371 }
1372""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1373 else:
1374 sub_cls = m_type[:-2] # Trim _t
1375 out.write("""
1376 %(var_name)s = %(sub_cls)s_new(%(v_name)s);
1377 TEST_ASSERT(%(var_name)s != NULL);
1378 value = %(sub_cls)s_%(v_name)s_populate(
1379 %(var_name)s, value);
1380 TEST_ASSERT(value != 0);
1381 %(cls)s_%(m_name)s_set(
1382 obj, %(var_name)s);
1383 %(sub_cls)s_delete(%(var_name)s);
1384""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1385 var_name=var_name_map(m_type),
1386 v_name=loxi_utils.version_to_name(version)))
1387
1388 out.write("""
1389 return value;
1390}
1391""")
1392
1393 out.write("""
1394/**
1395 * Check all members of an object of type %(cls)s
1396 * populated by the above function
1397 * @param obj Pointer to an object to check
1398 * @param value Starting value for checking
1399 * @returns The value after increments for this object's values
1400 */
1401
1402int
1403%(cls)s_%(v_name)s_check(
1404 %(cls)s_t *obj, int value)
1405{
1406""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1407 members, member_types = loxi_utils.all_member_types_get(cls, version)
1408 for m_type in member_types:
1409 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1410 continue
1411 if loxi_utils.type_is_of_object(m_type):
1412 continue
1413 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1414 out.write("""
1415 value = %(cls)s_%(v_name)s_check_scalars(
1416 obj, value);
1417 TEST_ASSERT(value != 0);
1418""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1419
1420 for member in members:
1421 m_type = member["m_type"]
1422 m_name = member["name"]
1423 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1424 continue
1425 if loxi_utils.skip_member_name(m_name):
1426 continue
1427 if m_type == "of_match_t":
1428 out.write("""\
1429 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1430 value = of_match_check(&%(var_name)s, %(v_name)s, value);
1431""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1432 v_name=loxi_utils.version_to_name(version)))
1433 elif m_type == "of_octets_t":
1434 out.write("""\
1435 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1436 value = of_octets_check(&%(var_name)s, value);
1437""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1438 v_name=loxi_utils.version_to_name(version)))
1439 else:
1440 sub_cls = m_type[:-2] # Trim _t
1441 out.write("""
1442 { /* Use get/delete to access on check */
1443 %(m_type)s *%(m_name)s_ptr;
1444
1445 %(m_name)s_ptr = %(cls)s_%(m_name)s_get(obj);
1446 TEST_ASSERT(%(m_name)s_ptr != NULL);
1447 value = %(sub_cls)s_%(v_name)s_check(
1448 %(m_name)s_ptr, value);
1449 TEST_ASSERT(value != 0);
1450 %(sub_cls)s_delete(%(m_name)s_ptr);
1451 }
1452""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1453 var_name=var_name_map(m_type),
1454 v_name=loxi_utils.version_to_name(version)))
1455
1456 out.write("""
1457 /* We shoehorn a test of the dup functions here */
1458 {
1459 %(cls)s_t *dup;
1460
1461 TEST_ASSERT((dup = %(cls)s_dup(obj)) != NULL);
1462 TEST_ASSERT(dup->length == obj->length);
1463 TEST_ASSERT(dup->object_id == obj->object_id);
1464 TEST_ASSERT(dup->version == obj->version);
1465 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1466 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1467 of_object_delete((of_object_t *)dup);
1468
1469 /* And now for the generic dup function */
1470 TEST_ASSERT((dup = (%(cls)s_t *)
1471 of_object_dup(obj)) != NULL);
1472 TEST_ASSERT(dup->length == obj->length);
1473 TEST_ASSERT(dup->object_id == obj->object_id);
1474 TEST_ASSERT(dup->version == obj->version);
1475 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1476 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1477 of_object_delete((of_object_t *)dup);
1478 }
1479
1480 return value;
1481}
1482""" % dict(cls=cls))
1483
1484def unified_accessor_test_case(out, cls, version):
1485 """
1486 Generate one test case for the given version and class
1487 """
1488
1489 members, member_types = scalar_member_types_get(cls, version)
1490 length = of_g.base_length[(cls, version)]
1491 v_name = loxi_utils.version_to_name(version)
1492
1493 out.write("""
1494static int
1495test_%(cls)s_%(v_name)s(void)
1496{
1497 %(cls)s_t *obj;
1498 obj = %(cls)s_new(%(v_name)s);
1499 TEST_ASSERT(obj != NULL);
1500 TEST_ASSERT(obj->version == %(v_name)s);
1501 TEST_ASSERT(obj->length == %(length)d);
1502 TEST_ASSERT(obj->parent == NULL);
1503 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001504""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001505 v_name=v_name, length=length, version=version))
1506 if (not type_maps.class_is_virtual(cls)) or loxi_utils.class_is_list(cls):
1507 out.write("""
1508 if (obj->wire_length_get != NULL) {
1509 int length;
1510
1511 obj->wire_length_get((of_object_t *)obj, &length);
1512 TEST_ASSERT(length == %(length)d);
1513 }
1514 if (obj->wire_type_get != NULL) {
1515 of_object_id_t obj_id;
1516
1517 obj->wire_type_get((of_object_t *)obj, &obj_id);
1518 TEST_ASSERT(obj_id == %(u_cls)s);
1519 }
1520
1521 /* Set up incrementing values for members */
1522 TEST_ASSERT(%(cls)s_%(v_name)s_populate(
1523 obj, 1) != 0);
1524
1525 /* Check values just set */
1526 TEST_ASSERT(%(cls)s_%(v_name)s_check(
1527 obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001528""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001529 v_name=v_name, length=length, version=version))
1530
1531 out.write("""
1532 %(cls)s_delete(obj);
1533
1534 /* To do: Check memory */
1535 return TEST_PASS;
1536}
1537""" % dict(cls=cls))
1538
1539
1540def gen_unified_accessor_funs(out):
1541 for version in of_g.of_version_range:
1542 for cls in of_g.standard_class_order:
1543 if not loxi_utils.class_in_version(cls, version):
1544 continue
1545 if cls in type_maps.inheritance_map:
1546 continue
1547 elif loxi_utils.class_is_list(cls):
1548 gen_list_setup_check(out, cls, version)
1549 else:
1550 gen_class_setup_check(out, cls, version)
1551
1552def gen_unified_accessor_tests(out, name):
1553 loxi_utils.gen_c_copy_license(out)
1554 out.write("""
1555/**
1556 *
1557 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1558 *
1559 * Unified simple class instantiation tests for all versions
1560 */
1561
1562#include <locitest/test_common.h>
1563""")
1564 for version in of_g.of_version_range:
1565 for cls in of_g.standard_class_order:
1566 if not loxi_utils.class_in_version(cls, version):
1567 continue
1568 if cls in type_maps.inheritance_map:
1569 continue
1570 unified_accessor_test_case(out, cls, version)
1571
1572 out.write("""
1573int
1574run_unified_accessor_tests(void)
1575{
1576""")
1577 for version in of_g.of_version_range:
1578 v_name = loxi_utils.version_to_name(version)
1579 for cls in of_g.standard_class_order:
1580 if not loxi_utils.class_in_version(cls, version):
1581 continue
1582 if cls in type_maps.inheritance_map:
1583 continue
1584 test_name = "%s_%s" % (cls, v_name)
1585 out.write(" RUN_TEST(%s);\n" % test_name)
1586
1587 out.write(" return TEST_PASS;\n}\n");
1588
1589
1590
1591################################################################
1592#
1593# Object duplication functions
1594#
1595# These exercise the accessors to create duplicate objects.
1596# They are used in the LOCI test shim which sits in an OF
1597# protocol stream.
1598#
1599# TODO
1600# Resolve version stuff
1601# Complete list dup
1602
1603def gen_dup_list(out, cls, version):
1604 ver_name = loxi_utils.version_to_name(version)
1605 elt_type = loxi_utils.list_to_entry_type(cls)
1606 out.write("""
1607/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001608 * Duplicate a list of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001609 * using accessor functions
1610 * @param src Pointer to object to be duplicated
1611 * @returns A new object of type %(cls)s.
1612 *
1613 * The caller is responsible for deleting the returned value
1614 */
1615%(cls)s_t *
1616%(cls)s_%(ver_name)s_dup(
1617 %(cls)s_t *src)
1618{
1619 %(elt_type)s_t src_elt;
1620 %(elt_type)s_t *dst_elt;
1621 int rv;
1622 %(cls)s_t *dst;
1623
1624 if ((dst = %(cls)s_new(src->version)) == NULL) {
1625 return NULL;
1626 }
1627""" % dict(elt_type=elt_type, cls=cls, ver_name=ver_name))
1628
1629 out.write("""
1630 %(u_cls)s_ITER(src, &src_elt, rv) {
1631 if ((dst_elt = %(elt_type)s_%(ver_name)s_dup(&src_elt)) == NULL) {
1632 of_object_delete((of_object_t *)dst);
1633 return NULL;
1634 }
1635 _TRY_FREE(%(cls)s_append(dst, dst_elt),
1636 dst, NULL);
1637 of_object_delete((of_object_t *)dst_elt);
1638 }
1639
1640 return dst;
1641}
1642""" % dict(u_cls=cls.upper(), elt_type=elt_type, cls=cls, ver_name=ver_name))
1643
1644
1645def gen_dup_inheritance(out, cls, version):
1646 ver_name = loxi_utils.version_to_name(version)
1647 out.write("""
1648/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001649 * Duplicate a super class object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001650 * @param src Pointer to object to be duplicated
1651 * @returns A new object of type %(cls)s.
1652 *
1653 * The caller is responsible for deleting the returned value
1654 */
1655%(cls)s_t *
1656%(cls)s_%(ver_name)s_dup(
1657 %(cls)s_t *src)
1658{
1659""" % dict(cls=cls, ver_name=ver_name))
1660
1661 # For each subclass, check if this is an instance of that subclass
1662 version_classes = type_maps.inheritance_data[cls][version]
1663 for sub_cls in version_classes:
1664 sub_enum = (cls + "_" + sub_cls).upper()
1665 out.write("""
1666 if (src->header.object_id == %(sub_enum)s) {
1667 return (%(cls)s_t *)%(cls)s_%(sub_cls)s_%(ver_name)s_dup(
1668 &src->%(sub_cls)s);
1669 }
1670""" % dict(sub_cls=sub_cls, ver_name=ver_name, sub_enum=sub_enum, cls=cls))
1671
1672 out.write("""
1673 return NULL;
1674}
1675""")
1676
1677
1678def gen_dup_cls(out, cls, version):
1679 """
1680 Generate duplication routine for class cls
1681 """
1682 ver_name = loxi_utils.version_to_name(version)
1683
1684 out.write("""
1685/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001686 * Duplicate an object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001687 * using accessor functions
1688 * @param src Pointer to object to be duplicated
1689 * @returns A new object of type %(cls)s.
1690 *
1691 * The caller is responsible for deleting the returned value
1692 */
1693%(cls)s_t *
1694%(cls)s_%(ver_name)s_dup(
1695 %(cls)s_t *src)
1696{
1697 %(cls)s_t *dst;
1698""" % dict(cls=cls, ver_name=ver_name))
1699
1700 # Get members and types for the class
1701 members, member_types = loxi_utils.all_member_types_get(cls, version)
1702
1703 # Add declarations for each member type
1704 for m_type in member_types:
1705 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1706 # Declare instance of these
1707 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1708 else:
1709 out.write("""
1710 %(m_type)s src_%(v_name)s;
1711 %(m_type)s *dst_%(v_name)s;
1712""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
1713
1714 out.write("""
1715 if ((dst = %(cls)s_new(src->version)) == NULL) {
1716 return NULL;
1717 }
1718""" % dict(cls=cls))
1719
1720 for member in members:
1721 m_type = member["m_type"]
1722 m_name = member["name"]
1723 if loxi_utils.skip_member_name(m_name):
1724 continue
1725 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1726 out.write("""
1727 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1728 %(cls)s_%(m_name)s_set(dst, %(v_name)s);
1729""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1730 elif m_type in ["of_match_t", "of_octets_t"]:
1731 out.write("""
1732 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1733 %(cls)s_%(m_name)s_set(dst, &%(v_name)s);
1734""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1735 else:
1736 sub_cls = m_type[:-2] # Trim _t
1737 out.write("""
1738 %(cls)s_%(m_name)s_bind(
1739 src, &src_%(v_name)s);
1740 dst_%(v_name)s = %(sub_cls)s_%(ver_name)s_dup(&src_%(v_name)s);
1741 if (dst_%(v_name)s == NULL) {
1742 %(cls)s_delete(dst);
1743 return NULL;
1744 }
1745 %(cls)s_%(m_name)s_set(dst, dst_%(v_name)s);
1746 %(sub_cls)s_delete(dst_%(v_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001747""" % dict(sub_cls=sub_cls, cls=cls, m_name=m_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001748 v_name=var_name_map(m_type), ver_name=ver_name))
1749
1750 out.write("""
1751 return dst;
1752}
1753""")
1754
1755def gen_version_dup(out=sys.stdout):
1756 """
1757 Generate duplication routines for each object type
1758 """
1759 out.write("""
1760/* Special try macro for duplicating */
1761#define _TRY_FREE(op, obj, rv) do { \\
1762 int _rv; \\
1763 if ((_rv = (op)) < 0) { \\
1764 LOCI_LOG_ERROR("ERROR %d at %s:%d\\n", _rv, __FILE__, __LINE__); \\
1765 of_object_delete((of_object_t *)(obj)); \\
1766 return (rv); \\
1767 } \\
1768 } while (0)
1769""")
1770
1771 for version in of_g.of_version_range:
1772 for cls in of_g.standard_class_order:
1773 if not loxi_utils.class_in_version(cls, version):
1774 continue
1775 if cls in type_maps.inheritance_map:
1776 gen_dup_inheritance(out, cls, version)
1777 elif loxi_utils.class_is_list(cls):
1778 gen_dup_list(out, cls, version)
1779 else:
1780 gen_dup_cls(out, cls, version)
1781
1782def gen_dup(out=sys.stdout):
1783 """
1784 Generate non-version specific duplication routines for each object type
1785 """
1786
1787 for cls in of_g.standard_class_order:
1788 out.write("""
1789%(cls)s_t *
1790%(cls)s_dup(
1791 %(cls)s_t *src)
1792{
1793""" % dict(cls=cls))
1794 for version in of_g.of_version_range:
1795 if not loxi_utils.class_in_version(cls, version):
1796 continue
1797 hdr = "header." if cls in type_maps.inheritance_map else ""
1798
1799 ver_name = loxi_utils.version_to_name(version)
1800 out.write("""
1801 if (src->%(hdr)sversion == %(ver_name)s) {
1802 return %(cls)s_%(ver_name)s_dup(src);
1803 }
1804""" % dict(cls=cls, ver_name=ver_name, hdr=hdr))
1805
1806 out.write("""
1807 /* Class not supported in given version */
1808 return NULL;
1809}
1810""")
1811
1812def dup_c_gen(out, name):
1813 """
1814 Generate the C file for duplication functions
1815 """
1816 loxi_utils.gen_c_copy_license(out)
1817 out.write("""\
1818/*
1819 * Duplication functions for all OF objects
1820 *
1821 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1822 *
1823 * These are test functions for exercising accessors. You can call
1824 * of_object_dup for an efficient duplication.
1825 */
1826
1827#define DISABLE_WARN_UNUSED_RESULT
1828#include "loci_log.h"
1829#include <locitest/of_dup.h>
1830
1831""")
1832
1833 gen_version_dup(out)
1834 gen_dup(out)
1835
1836
1837def dup_h_gen(out, name):
1838 """
1839 Generate the header file for duplication functions
1840 """
1841
1842 loxi_utils.gen_c_copy_license(out)
1843 out.write("""
1844/*
1845 * Duplication function header file
1846 *
1847 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1848 */
1849
1850#if !defined(_OF_DUP_H_)
1851#define _OF_DUP_H_
1852
1853#include <loci/loci.h>
1854""")
1855
1856 for cls in of_g.standard_class_order:
1857 out.write("""
1858extern %(cls)s_t *
1859 %(cls)s_dup(
1860 %(cls)s_t *src);
1861""" % dict(cls=cls))
1862
1863 for version in of_g.of_version_range:
1864 for cls in of_g.standard_class_order:
1865 if not loxi_utils.class_in_version(cls, version):
1866 continue
1867 ver_name = loxi_utils.version_to_name(version)
1868 out.write("""
1869extern %(cls)s_t *
1870 %(cls)s_%(ver_name)s_dup(
1871 %(cls)s_t *src);
1872""" % dict(cls=cls, ver_name=ver_name))
1873
1874 out.write("\n#endif /* _OF_DUP_H_ */\n")
1875
1876def gen_log_test(out):
1877 """
1878 Generate test for obj log calls
1879
1880 Define a trivial handler for object logging; call all obj log fns
1881 """
1882 out.write("""
1883
1884/**
1885 * Test object dump functions
1886 */
1887
1888int
1889test_dump_objs(void)
1890{
1891 of_object_t *obj;
1892
1893 FILE *out = fopen("/dev/null", "w");
1894
1895 /* Call each obj dump function */
1896""")
1897 for version in of_g.of_version_range:
1898 for j, cls in enumerate(of_g.all_class_order):
1899 if not loxi_utils.class_in_version(cls, version):
1900 continue
1901 if cls in type_maps.inheritance_map:
1902 continue
1903 out.write("""
1904 obj = (of_object_t *)%(cls)s_new(%(version)s);
1905 of_object_dump((loci_writer_f)fprintf, out, obj);
1906 of_object_delete(obj);
1907""" % dict(cls=cls, version=of_g.of_version_wire2name[version]))
Andreas Wundsam53256162013-05-02 14:05:53 -07001908
Rich Lanea06d0c32013-03-25 08:52:03 -07001909 out.write("""
1910 fclose(out);
1911 return TEST_PASS;
1912}
1913""")
1914
1915def gen_ident_tests(out):
1916 """
1917 Generate tests for identifiers
1918
1919 For all idents, instantiate, test version supported macros
1920 For flags, set it, test it, clear it, test it.
1921 """
1922 out.write("""
1923/**
1924 * Test cases for all flag accessor macros
1925 * These only test self consistency (and that they compile)
1926 */
1927int
1928test_ident_macros(void)
1929{
1930 int value __attribute__((unused));
1931 uint32_t flags;
1932
1933""")
1934
1935 for ident, info in of_g.identifiers.items():
1936 if not identifiers.defined_versions_agree(of_g.identifiers,
1937 of_g.target_version_list,
1938 ident):
1939 # @fixme
1940 continue
1941 out.write(" value = %s;\n" % ident)
1942 for version in of_g.target_version_list:
1943 if version in info["values_by_version"].keys():
1944 out.write(" TEST_ASSERT(%s_SUPPORTED(%s));\n" %
1945 (ident, of_g.of_version_wire2name[version]))
1946 else:
1947 out.write(" TEST_ASSERT(!%s_SUPPORTED(%s));\n" %
1948 (ident, of_g.of_version_wire2name[version]))
1949 if flags.ident_is_flag(ident):
1950 # Grab first supported version
1951 for version in info["values_by_version"]:
1952 break
1953 out.write("""
1954 flags = 0;
1955 %(ident)s_SET(flags, %(ver_name)s);
1956 TEST_ASSERT(flags == %(ident)s_BY_VERSION(%(ver_name)s));
1957 TEST_ASSERT(%(ident)s_TEST(flags, %(ver_name)s));
1958 %(ident)s_CLEAR(flags, %(ver_name)s);
1959 TEST_ASSERT(flags == 0);
1960 TEST_ASSERT(!%(ident)s_TEST(flags, %(ver_name)s));
1961""" % dict(ident=ident, ver_name=of_g.of_version_wire2name[version]))
1962
1963 out.write("""
1964 return TEST_PASS;
1965}
1966""")
1967