blob: 74aef8ab793be4acc82d59a0a71492f63796a794 [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
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +090057is done with mcheck (if available).
Rich Lanea06d0c32013-03-25 08:52:03 -070058
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
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900404/* mcheck is a glibc extension */
405#if defined(__linux__)
Rich Lanea06d0c32013-03-25 08:52:03 -0700406#include <mcheck.h>
407#define MCHECK_INIT mcheck(NULL)
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900408#else
Rich Lanea06d0c32013-03-25 08:52:03 -0700409#define MCHECK_INIT do { } while (0)
410#endif
411
412/**
413 * Exit on error if set to 1
414 */
415int exit_on_error = 1;
416
417/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700418 * Global error state: 0 is okay, 1 is error
Rich Lanea06d0c32013-03-25 08:52:03 -0700419 */
420int global_error = 0;
421
422extern int run_unified_accessor_tests(void);
423extern int run_match_tests(void);
424extern int run_utility_tests(void);
425
426extern int run_scalar_acc_tests(void);
427extern int run_list_tests(void);
428extern int run_message_tests(void);
429
430/**
431 * Macros for initializing and checking scalar types
432 *
433 * @param var The variable being initialized or checked
434 * @param val The integer value to set/check against, see below
435 *
436 * Note that equality means something special for strings. Each byte
437 * is initialized to an incrementing value. So check is done against that.
438 *
439 */
440
441""")
442 for t in scalar_types:
443 if t in integer_types:
444 out.write("""
445#define VAR_%s_INIT(var, val) var = (%s)(val)
446#define VAR_%s_CHECK(var, val) ((var) == (%s)(val))
447""" % (t.upper(), t, t.upper(), t))
448 else:
449 out.write("""
450#define VAR_%s_INIT(var, val) \\
451 of_test_str_fill((uint8_t *)&(var), val, sizeof(var))
452#define VAR_%s_CHECK(var, val) \\
453 of_test_str_check((uint8_t *)&(var), val, sizeof(var))
454""" % (t.upper(), t.upper()))
455
456 gen_fill_string(out)
457 gen_scalar_set_check_funs(out)
458 gen_list_set_check_funs(out)
459 gen_unified_accessor_funs(out)
460
461 gen_ident_tests(out)
462 gen_log_test(out)
463
464def gen_message_scalar_test(out, name):
465 """
466 Generate test cases for message objects, scalar accessors
467 """
468
469 loxi_utils.gen_c_copy_license(out)
470 out.write("""
471/**
472 *
473 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
474 *
475 * Message-scalar tests for all versions
476 */
477
478#include <locitest/test_common.h>
479""")
480 for version in of_g.of_version_range:
481 v_name = loxi_utils.version_to_name(version)
482 out.write("""
483/**
484 * Message-scalar tests for version %s
485 */
486""" % v_name)
487 for cls in of_g.standard_class_order:
488 if cls in type_maps.inheritance_map:
489 continue
490 if version in of_g.unified[cls]:
491 message_scalar_test(out, version, cls)
492
493 out.write("""
494int
495run_scalar_acc_tests(void)
496{
497""")
498 for version in of_g.of_version_range:
499 v_name = loxi_utils.version_to_name(version)
500 for cls in of_g.standard_class_order:
501 if cls in type_maps.inheritance_map:
502 continue
503 if version in of_g.unified[cls]:
504 test_name = "%s_%s" % (cls, v_name)
505 out.write(" RUN_TEST(%s_scalar);\n" % test_name)
506
507 out.write(" return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -0700508
Rich Lanea06d0c32013-03-25 08:52:03 -0700509def message_scalar_test(out, version, cls):
510 """
511 Generate one test case for the given version and class
512 """
513
514 members, member_types = scalar_member_types_get(cls, version)
515 length = of_g.base_length[(cls, version)]
516 v_name = loxi_utils.version_to_name(version)
517
518 out.write("""
519static int
520test_%(cls)s_%(v_name)s_scalar(void)
521{
522 %(cls)s_t *obj;
523
524 obj = %(cls)s_new(%(v_name)s);
525 TEST_ASSERT(obj != NULL);
526 TEST_ASSERT(obj->version == %(v_name)s);
527 TEST_ASSERT(obj->length == %(length)d);
528 TEST_ASSERT(obj->parent == NULL);
529 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -0700530""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700531 v_name=v_name, length=length, version=version))
532 if not type_maps.class_is_virtual(cls):
533 out.write("""
534 if (obj->wire_length_get != NULL) {
535 int length;
536
537 obj->wire_length_get((of_object_t *)obj, &length);
538 TEST_ASSERT(length == %(length)d);
539 }
540
541 /* Set up incrementing values for scalar members */
542 %(cls)s_%(v_name)s_populate_scalars(obj, 1);
543
544 /* Check values just set */
545 TEST_ASSERT(%(cls)s_%(v_name)s_check_scalars(obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700546""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700547 v_name=v_name, length=length, version=version))
548
549 out.write("""
550 %(cls)s_delete(obj);
551
552 /* To do: Check memory */
553 return TEST_PASS;
554}
555""" % dict(cls=cls))
556
557# Get the members and list of scalar types for members of a given class
558def scalar_member_types_get(cls, version):
559 member_types = []
560
561 if not version in of_g.unified[cls]:
562 return ([], [])
563
564 if "use_version" in of_g.unified[cls][version]:
565 v = of_g.unified[cls][version]["use_version"]
566 members = of_g.unified[cls][v]["members"]
567 else:
568 members = of_g.unified[cls][version]["members"]
569 # Accumulate variables that are supported
570 for member in members:
571 m_type = member["m_type"]
572 m_name = member["name"]
Andreas Wundsam53256162013-05-02 14:05:53 -0700573 if (not loxi_utils.type_is_scalar(m_type) or
Rich Lanea06d0c32013-03-25 08:52:03 -0700574 ignore_member(cls, version, m_name, m_type)):
575 continue
576 if not m_type in member_types:
577 member_types.append(m_type)
578
579 return (members, member_types)
580
581def scalar_funs_instance(out, cls, version, members, member_types):
582 """
583 Generate one instance of scalar set/check functions
584 """
585 out.write("""
586/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700587 * Populate the scalar values in obj of type %(cls)s,
588 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700589 * @param obj Pointer to an object to populate
590 * @param value The seed value to use in populating the object
591 * @returns The value after increments for this object's values
592 */
593int %(cls)s_%(v_name)s_populate_scalars(
594 %(cls)s_t *obj, int value) {
595""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
596 # Declare string types
597 for t in member_types:
598 out.write(" %s %s;\n" % (t, var_name_map(t)))
599 for member in members:
600 m_type = member["m_type"]
601 m_name = member["name"]
602 if (not loxi_utils.type_is_scalar(m_type) or
603 ignore_member(cls, version, m_name, m_type)):
604 continue
605 v_name = var_name_map(m_type);
606 out.write("""
607 VAR_%(u_type)s_INIT(%(v_name)s, value);
608 %(cls)s_%(m_name)s_set(obj, %(v_name)s);
609 value += 1;
610""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
611 out.write("""
612 return value;
613}
614""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700615
Rich Lanea06d0c32013-03-25 08:52:03 -0700616 out.write("""
617/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700618 * Check scalar values in obj of type %(cls)s,
619 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700620 * @param obj Pointer to an object to check
621 * @param value Starting value for checking
622 * @returns The value after increments for this object's values
623 */
624int %(cls)s_%(v_name)s_check_scalars(
625 %(cls)s_t *obj, int value) {
626""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
627
628 for t in member_types:
629 out.write(" %s %s;\n" % (t, var_name_map(t)))
630 for member in members:
631 m_type = member["m_type"]
632 m_name = member["name"]
633 if (not loxi_utils.type_is_scalar(m_type) or
634 ignore_member(cls, version, m_name, m_type)):
635 continue
636 v_name = var_name_map(m_type);
637 out.write("""
638 %(cls)s_%(m_name)s_get(obj, &%(v_name)s);
639 TEST_ASSERT(VAR_%(u_type)s_CHECK(%(v_name)s, value));
640 value += 1;
641""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
642
643 out.write("""
644 return value;
645}
646
647""")
648
649def gen_scalar_set_check_funs(out):
650 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700651 For each object class with scalar members, generate functions that
Rich Lanea06d0c32013-03-25 08:52:03 -0700652 set and check their values
653 """
654 for version in of_g.of_version_range:
655 for cls in of_g.standard_class_order:
656 (members, member_types) = scalar_member_types_get(cls, version)
657 scalar_funs_instance(out, cls, version, members, member_types)
658
659
660# Helper function to set up a subclass instance for a test
661def setup_instance(out, cls, subcls, instance, v_name, inst_len, version):
662 base_type = loxi_utils.list_to_entry_type(cls)
663 setup_template = """
664 %(subcls)s_init(%(inst)s, %(v_name)s, -1, 1);
Andreas Wundsam53256162013-05-02 14:05:53 -0700665 %(cls)s_append_bind(list,
Rich Lanea06d0c32013-03-25 08:52:03 -0700666 (%(base_type)s_t *)%(inst)s);
667 value = %(subcls)s_%(v_name)s_populate(
668 %(inst)s, value);
669 cur_len += %(inst)s->length;
670 TEST_ASSERT(list->length == cur_len);
671"""
672 out.write("""
673 /* Append two instances of type %s */
674""" % subcls)
675 for i in range(2):
676 out.write(setup_template %
Andreas Wundsam53256162013-05-02 14:05:53 -0700677 dict(inst=instance, subcls=subcls, v_name=v_name,
678 base_type=base_type, cls=cls, inst_len=inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700679 version=version))
680
681def check_instance(out, cls, subcls, instance, v_name, inst_len, version, last):
682 check_template = ""
683 if inst_len >= 0:
684 check_template = """
685 TEST_ASSERT(%(inst)s->length == %(inst_len)d);
686 if (%(inst)s->wire_length_get != NULL) {
687 int length;
688
689 %(inst)s->wire_length_get(
690 (of_object_t *)&elt, &length);
691 TEST_ASSERT(length == %(inst_len)d);
692 }
693"""
694 check_template += """
695 TEST_ASSERT(%(inst)s->object_id == %(elt_name)s);
696 value = %(subcls)s_%(v_name)s_check(
697 %(inst)s, value);
698 TEST_ASSERT(value != 0);
699"""
700 out.write("\n /* Check two instances of type %s */" % instance)
701
Andreas Wundsam53256162013-05-02 14:05:53 -0700702 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700703 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
704 inst=instance, subcls=subcls,
705 v_name=loxi_utils.version_to_name(version)))
706 out.write("""\
707 TEST_OK(%(cls)s_next(list, &elt));
708""" % dict(cls=cls))
709
Andreas Wundsam53256162013-05-02 14:05:53 -0700710 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700711 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
712 inst=instance, subcls=subcls,
713 v_name=loxi_utils.version_to_name(version)))
714 if last:
715 out.write("""\
716 TEST_ASSERT(%(cls)s_next(list, &elt) == OF_ERROR_RANGE);
717""" % dict(cls=cls))
718 else:
719 out.write("""\
720 TEST_OK(%(cls)s_next(list, &elt));
721""" % dict(cls=cls))
722
723def setup_list_fn(out, version, cls):
724 """
725 Generate a helper function that populates a list with two
726 of each type of subclass it supports
727 """
728 out.write("""
729/**
730 * Set up a list of type %(cls)s with two of each type of subclass
731 */
732int
733list_setup_%(cls)s_%(v_name)s(
734 %(cls)s_t *list, int value)
735{
736""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
737 base_type = loxi_utils.list_to_entry_type(cls)
738 out.write("""
739 %(base_type)s_t elt;
740 int cur_len = 0;
741""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700742
Rich Lanea06d0c32013-03-25 08:52:03 -0700743 sub_classes = type_maps.sub_class_map(base_type, version)
744 v_name = loxi_utils.version_to_name(version)
745
746 if len(sub_classes) == 0:
747 out.write(" /* No subclasses for %s */\n"% base_type)
748 out.write(" %s_t *elt_p;\n" % base_type)
749 out.write("\n elt_p = &elt;\n")
750 else:
751 out.write(" /* Declare pointers for each subclass */\n")
752 for instance, subcls in sub_classes:
753 out.write(" %s_t *%s;\n" % (subcls, instance))
754 out.write("\n /* Instantiate pointers for each subclass */\n")
755 for instance, subcls in sub_classes:
756 out.write(" %s = &elt.%s;\n" % (instance, instance))
757
758 if len(sub_classes) == 0: # No inheritance case
759 inst_len = loxi_utils.base_type_to_length(base_type, version)
760 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
761 else:
762 for instance, subcls in sub_classes:
763 inst_len = of_g.base_length[(subcls, version)]
764 setup_instance(out, cls, subcls, instance, v_name, inst_len, version)
765 out.write("""
766
767 return value;
768}
769""")
770
771def check_list_fn(out, version, cls):
772 """
773 Generate a helper function that checks a list populated by above fn
774 """
775 out.write("""
776/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700777 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -0700778 * list_setup_%(cls)s_%(v_name)s
779 */
780int
781list_check_%(cls)s_%(v_name)s(
782 %(cls)s_t *list, int value)
783{
784""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
785 base_type = loxi_utils.list_to_entry_type(cls)
786 out.write("""
787 %(base_type)s_t elt;
788""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700789
Rich Lanea06d0c32013-03-25 08:52:03 -0700790 sub_classes = type_maps.sub_class_map(base_type, version)
791 v_name = loxi_utils.version_to_name(version)
792
793 if len(sub_classes) == 0:
794 out.write(" /* No subclasses for %s */\n"% base_type)
795 out.write(" %s_t *elt_p;\n" % base_type)
796 out.write("\n elt_p = &elt;\n")
797 else:
798 out.write(" /* Declare pointers for each subclass */\n")
799 for instance, subcls in sub_classes:
800 out.write(" %s_t *%s;\n" % (subcls, instance))
801 out.write("\n /* Instantiate pointers for each subclass */\n")
802 for instance, subcls in sub_classes:
803 out.write(" %s = &elt.%s;\n" % (instance, instance))
804
805 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
806 if len(sub_classes) == 0: # No inheritance case
807 if loxi_utils.class_is_var_len(base_type, version):
808 inst_len = -1
809 else:
810 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -0700811 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700812 version, True)
813 else:
814 count = 0
815 for instance, subcls in sub_classes:
816 count += 1
817 if loxi_utils.class_is_var_len(subcls, version):
818 inst_len = -1
819 else:
820 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -0700821 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700822 version, count==len(sub_classes))
823
824 out.write("""
825 return value;
826}
827""" % dict(base_type=base_type))
828
829def gen_list_set_check_funs(out):
830 for version in of_g.of_version_range:
831 for cls in of_g.ordered_list_objects:
832 if cls in type_maps.inheritance_map:
833 continue
834
835 if version in of_g.unified[cls]:
836 setup_list_fn(out, version, cls)
837 check_list_fn(out, version, cls)
838
839# Maybe: Get a map from list class to parent, mem_name of container
840
841def list_test(out, version, cls):
842 out.write("""
843static int
844test_%(cls)s_%(v_name)s(void)
845{
846""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
847 base_type = loxi_utils.list_to_entry_type(cls)
848
849 out.write(""" %(cls)s_t *list;
850 int value = 1;
851""" % dict(cls=cls, base_type=base_type))
852
853 out.write("""
854 list = %(cls)s_new(%(v_name)s);
855 TEST_ASSERT(list != NULL);
856 TEST_ASSERT(list->version == %(v_name)s);
857 TEST_ASSERT(list->length == 0);
858 TEST_ASSERT(list->parent == NULL);
859 TEST_ASSERT(list->object_id == %(enum_cls)s);
860
861 value = list_setup_%(cls)s_%(v_name)s(list, value);
862 TEST_ASSERT(value != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700863""" % dict(cls=cls, base_type=base_type, v_name=loxi_utils.version_to_name(version),
Rich Lanea06d0c32013-03-25 08:52:03 -0700864 enum_cls=loxi_utils.enum_name(cls)))
865
866 out.write("""
867 /* Now check values */
868 value = 1;
869 value = list_check_%(cls)s_%(v_name)s(list, value);
870 TEST_ASSERT(value != 0);
871""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
872
873 out.write("""
874 %(cls)s_delete(list);
875
876 return TEST_PASS;
877}
878""" % dict(cls=cls))
879
880def gen_list_test(out, name):
881 """
882 Generate base line test cases for lists
883 @param out The file handle to write to
884 """
885
886 loxi_utils.gen_c_copy_license(out)
887 out.write("""
888/**
889 *
890 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
891 *
892 * Message-scalar tests for all versions
893 */
894
895#include <locitest/test_common.h>
896""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700897
Rich Lanea06d0c32013-03-25 08:52:03 -0700898 for version in of_g.of_version_range:
899 v_name = loxi_utils.version_to_name(version)
900 out.write("""
901/**
902 * Baseline list tests for version %s
903 */
904""" % v_name)
905 for cls in of_g.ordered_list_objects:
906 if cls in type_maps.inheritance_map:
907 continue
908 if version in of_g.unified[cls]:
909 list_test(out, version, cls)
910
911 out.write("""
912int
913run_list_tests(void)
914{
915""")
916 for version in of_g.of_version_range:
917 v_name = loxi_utils.version_to_name(version)
918 for cls in of_g.ordered_list_objects:
919 if cls in type_maps.inheritance_map:
920 continue
921 if version in of_g.unified[cls]:
922 test_name = "%s_%s" % (cls, v_name)
923 out.write(" RUN_TEST(%s);\n" % test_name)
924
925 out.write("\n return TEST_PASS;\n}\n");
926
927def gen_match_test(out, name):
928 """
929 Generate baseline tests for match functions
930 """
931
932 loxi_utils.gen_c_copy_license(out)
933 out.write("""\
934/**
935 *
936 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
937 *
938 * Message-scalar tests for all versions
939 * @fixme These are mostly hard coded now.
940 */
941
942#include <locitest/test_common.h>
943
944static int
945test_match_1(void)
946{
947 of_match_v1_t *m_v1;
948 of_match_v2_t *m_v2;
949 of_match_v3_t *m_v3;
950 of_match_v4_t *m_v4;
951 of_match_t match;
952 int value = 1;
953 int idx;
954 uint32_t exp_value;
955
956 /* Verify default values for ip mask map */
957 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
958 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
959 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
960 if (idx < 32) {
961 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
962 }
963 }
964
965 TEST_ASSERT(of_ip_mask_map_set(17, 0xabcdef00) == OF_ERROR_NONE);
966 TEST_ASSERT(of_ip_mask_to_index(0xabcdef00) == 17);
967 TEST_ASSERT(of_ip_index_to_mask(17) == 0xabcdef00);
968
969 TEST_ASSERT(of_ip_mask_map_set(62, 0xabcdefff) == OF_ERROR_NONE);
970 TEST_ASSERT(of_ip_mask_to_index(0xabcdefff) == 62);
971 TEST_ASSERT(of_ip_index_to_mask(62) == 0xabcdefff);
972
973 /* Test re-init */
974 of_ip_mask_map_init();
975 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
976 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
977 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
978 if (idx < 32) {
979 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
980 }
981 }
982""")
983
984 for version in of_g.of_version_range:
985 out.write("""
986 /* Create/populate/convert and delete for version %(v_name)s */
987 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
988 TEST_ASSERT(m_v%(version)d != NULL);
989 TEST_ASSERT((value = of_match_populate(&match, %(v_name)s, value)) > 0);
990 TEST_OK(of_match_to_wire_match_v%(version)d(&match, m_v%(version)d));
991 of_match_v%(version)d_delete(m_v%(version)d);
992""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
993
994 out.write("""
995 return TEST_PASS;
996}
997""")
998
999 out.write("""
1000static int
1001test_match_2(void)
1002{
1003 of_match_v1_t *m_v1;
1004 of_match_v2_t *m_v2;
1005 of_match_v3_t *m_v3;
1006 of_match_v3_t *m_v4;
1007 of_match_t match1;
1008 of_match_t match2;
1009 int value = 1;
1010""")
1011
1012 for version in of_g.of_version_range:
1013 out.write("""
1014 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
1015 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
1016 TEST_ASSERT(m_v%(version)d != NULL);
1017 TEST_OK(of_match_to_wire_match_v%(version)d(&match1, m_v%(version)d));
1018 TEST_OK(of_match_v%(version)d_to_match(m_v%(version)d, &match2));
1019 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1020 of_match_v%(version)d_delete(m_v%(version)d);
1021""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1022
1023 out.write("""
1024 return TEST_PASS;
1025}
1026""")
1027
1028 out.write("""
1029static int
1030test_match_3(void)
1031{
1032 of_match_t match1;
1033 of_match_t match2;
1034 int value = 1;
1035 of_octets_t octets;
1036""")
1037 for version in of_g.of_version_range:
1038 out.write("""
1039 /* Serialize to version %(v_name)s */
1040 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001041 TEST_ASSERT(of_match_serialize(%(v_name)s, &match1, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001042 OF_ERROR_NONE);
Andreas Wundsam53256162013-05-02 14:05:53 -07001043 TEST_ASSERT(of_match_deserialize(%(v_name)s, &match2, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001044 OF_ERROR_NONE);
1045 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1046 FREE(octets.data);
1047""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1048
1049 out.write("""
1050 return TEST_PASS;
1051}
1052""")
1053
1054 out.write("""
1055int run_match_tests(void)
1056{
1057 RUN_TEST(match_1);
1058 RUN_TEST(match_2);
1059 RUN_TEST(match_3);
1060 RUN_TEST(match_utils);
1061
1062 return TEST_PASS;
1063}
1064""")
1065
1066def gen_msg_test(out, name):
1067 loxi_utils.gen_c_copy_license(out)
1068 out.write("""
1069/**
1070 *
1071 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1072 *
1073 * Message-scalar tests for all versions
1074 */
1075
1076#include <locitest/test_common.h>
1077""")
1078 for version in of_g.of_version_range:
1079 for cls in of_g.ordered_messages:
1080 if not (cls, version) in of_g.base_length:
1081 continue
1082 bytes = of_g.base_length[(cls, version)]
1083 out.write("""
1084static int
1085test_%(cls)s_create_%(v_name)s(void)
1086{
1087 %(cls)s_t *obj;
1088 uint8_t *msg_buf;
1089 int value;
1090 int len;
1091
1092 obj = %(cls)s_new(%(v_name)s);
1093 TEST_ASSERT(obj != NULL);
1094 TEST_ASSERT(obj->version == %(v_name)s);
1095 TEST_ASSERT(obj->length == %(bytes)d);
1096 TEST_ASSERT(obj->parent == NULL);
1097 TEST_ASSERT(obj->object_id == %(enum)s);
1098
1099 /* Set up incrementing values for scalar members */
1100 value = %(cls)s_%(v_name)s_populate_scalars(obj, 1);
1101 TEST_ASSERT(value != 0);
1102
1103 /* Grab the underlying buffer from the message */
1104 len = obj->length;
1105 of_object_wire_buffer_steal((of_object_t *)obj, &msg_buf);
1106 TEST_ASSERT(msg_buf != NULL);
1107 %(cls)s_delete(obj);
1108 /* TODO: */
1109 TEST_ASSERT(of_message_to_object_id(msg_buf, len) == %(enum)s);
1110 obj = %(cls)s_new_from_message(OF_BUFFER_TO_MESSAGE(msg_buf));
1111
1112 TEST_ASSERT(obj != NULL);
1113
1114 /* @fixme Set up all message objects (recursively?) */
1115
1116 value = %(cls)s_%(v_name)s_check_scalars(obj, 1);
1117 TEST_ASSERT(value != 0);
1118
1119 %(cls)s_delete(obj);
1120
1121 return TEST_PASS;
1122}
1123""" % dict(cls=cls, version=version, enum=loxi_utils.enum_name(cls),
1124 v_name=loxi_utils.version_to_name(version), bytes=bytes))
1125
1126 out.write("""
1127int
1128run_message_tests(void)
1129{
1130""")
1131 for version in of_g.of_version_range:
1132 for cls in of_g.ordered_messages:
1133 if not (cls, version) in of_g.base_length:
1134 continue
1135 test_name = "%s_create_%s" % (cls, loxi_utils.version_to_name(version))
1136 out.write(" RUN_TEST(%s);\n" % test_name)
1137
1138 out.write("\n return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -07001139
Rich Lanea06d0c32013-03-25 08:52:03 -07001140
1141def gen_list_setup_check(out, cls, version):
1142 """
1143 Generate functions that populate and check a list with two
1144 of each type of subclass it supports
1145 """
1146 out.write("""
1147/**
1148 * Populate a list of type %(cls)s with two of each type of subclass
1149 * @param list Pointer to the list to be populated
1150 * @param value The seed value to use in populating the list
1151 * @returns The value after increments for this object's values
1152 */
1153int
1154%(cls)s_%(v_name)s_populate(
1155 %(cls)s_t *list, int value)
1156{
1157""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1158 base_type = loxi_utils.list_to_entry_type(cls)
1159 out.write("""
1160 %(base_type)s_t elt;
1161 int cur_len = 0;
1162""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001163
Rich Lanea06d0c32013-03-25 08:52:03 -07001164 sub_classes = type_maps.sub_class_map(base_type, version)
1165 v_name = loxi_utils.version_to_name(version)
1166
1167 if len(sub_classes) == 0:
1168 out.write(" /* No subclasses for %s */\n"% base_type)
1169 out.write(" %s_t *elt_p;\n" % base_type)
1170 out.write("\n elt_p = &elt;\n")
1171 else:
1172 out.write(" /* Declare pointers for each subclass */\n")
1173 for instance, subcls in sub_classes:
1174 out.write(" %s_t *%s;\n" % (subcls, instance))
1175 out.write("\n /* Instantiate pointers for each subclass */\n")
1176 for instance, subcls in sub_classes:
1177 out.write(" %s = &elt.%s;\n" % (instance, instance))
1178
1179# if type_maps.class_is_virtual(base_type):
1180# out.write("""\
1181# TEST_OK(%(base_type)s_header_init(
1182# (%(base_type)s_header_t *)&elt, %(v_name)s, -1, 1));
1183# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1184# else:
1185# out.write("""\
1186# TEST_OK(%(base_type)s_init(&elt, %(v_name)s, -1, 1));
1187# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1188
1189 if len(sub_classes) == 0: # No inheritance case
1190 inst_len = loxi_utils.base_type_to_length(base_type, version)
1191 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
1192 else:
1193 for instance, subcls in sub_classes:
1194 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001195 setup_instance(out, cls, subcls, instance, v_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001196 inst_len, version)
1197 out.write("""
1198 return value;
1199}
1200""")
1201 out.write("""
1202/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001203 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -07001204 * %(cls)s_%(v_name)s_populate
1205 * @param list Pointer to the list that was populated
1206 * @param value Starting value for checking
1207 * @returns The value after increments for this object's values
1208 */
1209int
1210%(cls)s_%(v_name)s_check(
1211 %(cls)s_t *list, int value)
1212{
1213""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1214 base_type = loxi_utils.list_to_entry_type(cls)
1215 out.write("""
1216 %(base_type)s_t elt;
1217 int count = 0;
1218 int rv;
1219""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001220
Rich Lanea06d0c32013-03-25 08:52:03 -07001221
1222 sub_classes = type_maps.sub_class_map(base_type, version)
1223 v_name = loxi_utils.version_to_name(version)
1224
1225 if len(sub_classes) == 0:
1226 entry_count = 2
1227 out.write(" /* No subclasses for %s */\n"% base_type)
1228 out.write(" %s_t *elt_p;\n" % base_type)
1229 out.write("\n elt_p = &elt;\n")
1230 else:
1231 entry_count = 2 * len(sub_classes) # Two of each type appended
1232 out.write(" /* Declare pointers for each subclass */\n")
1233 for instance, subcls in sub_classes:
1234 out.write(" %s_t *%s;\n" % (subcls, instance))
1235 out.write("\n /* Instantiate pointers for each subclass */\n")
1236 for instance, subcls in sub_classes:
1237 out.write(" %s = &elt.%s;\n" % (instance, instance))
1238
1239 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
1240 if len(sub_classes) == 0: # No inheritance case
1241 if loxi_utils.class_is_var_len(base_type, version):
1242 inst_len = -1
1243 else:
1244 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -07001245 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001246 version, True)
1247 else:
1248 count = 0
1249 for instance, subcls in sub_classes:
1250 count += 1
1251 if loxi_utils.class_is_var_len(subcls, version):
1252 inst_len = -1
1253 else:
1254 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001255 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001256 version, count==len(sub_classes))
1257 out.write("""
1258""" % dict(base_type=base_type))
1259
1260 out.write("""
1261 /* Do an iterate to test the iterator */
1262 %(u_cls)s_ITER(list, &elt, rv) {
1263 count += 1;
1264 }
1265
1266 TEST_ASSERT(rv == OF_ERROR_RANGE);
1267 TEST_ASSERT(count == %(entry_count)d);
1268
1269 /* We shoehorn a test of the dup functions here */
1270 {
1271 %(cls)s_t *dup;
1272
1273 TEST_ASSERT((dup = %(cls)s_dup(list)) != NULL);
1274 TEST_ASSERT(dup->length == list->length);
1275 TEST_ASSERT(dup->object_id == list->object_id);
1276 TEST_ASSERT(dup->version == list->version);
1277 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1278 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1279 of_object_delete((of_object_t *)dup);
1280
1281 /* And now for the generic dup function */
1282 TEST_ASSERT((dup = (%(cls)s_t *)
1283 of_object_dup(list)) != NULL);
1284 TEST_ASSERT(dup->length == list->length);
1285 TEST_ASSERT(dup->object_id == list->object_id);
1286 TEST_ASSERT(dup->version == list->version);
1287 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1288 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1289 of_object_delete((of_object_t *)dup);
1290 }
1291
1292 return value;
1293}
1294""" % dict(cls=cls, u_cls=cls.upper(), entry_count=entry_count))
1295
1296
1297def gen_class_setup_check(out, cls, version):
1298 out.write("""
1299/**
1300 * Populate all members of an object of type %(cls)s
1301 * with incrementing values
1302 * @param obj Pointer to an object to populate
1303 * @param value The seed value to use in populating the object
1304 * @returns The value after increments for this object's values
1305 */
1306
1307int
1308%(cls)s_%(v_name)s_populate(
1309 %(cls)s_t *obj, int value)
1310{
1311""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1312 members, member_types = loxi_utils.all_member_types_get(cls, version)
1313 for m_type in member_types:
1314 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1315 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1316 else:
1317 out.write(" %s *%s;\n" % (m_type, var_name_map(m_type)))
1318 out.write("""
1319 /* Run thru accessors after new to ensure okay */
1320""")
1321 for member in members:
1322 m_type = member["m_type"]
1323 m_name = member["name"]
1324 if loxi_utils.skip_member_name(m_name):
1325 continue
1326 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1327 out.write("""\
1328 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1329""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1330 else:
1331 sub_cls = m_type[:-2] # Trim _t
1332 out.write("""\
1333 {
1334 %(sub_cls)s_t sub_cls;
1335
1336 /* Test bind */
1337 %(cls)s_%(m_name)s_bind(obj, &sub_cls);
1338 }
Andreas Wundsam53256162013-05-02 14:05:53 -07001339""" % dict(var_name=var_name_map(m_type), cls=cls,
Rich Lanea06d0c32013-03-25 08:52:03 -07001340 m_name=m_name, sub_cls=sub_cls,
1341 v_name=loxi_utils.version_to_name(version)))
1342
1343 out.write("""
1344 value = %(cls)s_%(v_name)s_populate_scalars(
1345 obj, value);
1346 TEST_ASSERT(value != 0);
1347""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1348
1349 for member in members:
1350 m_type = member["m_type"]
1351 m_name = member["name"]
1352 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1353 continue
1354 if loxi_utils.skip_member_name(m_name):
1355 continue
1356 if m_type == "of_match_t":
1357 out.write("""\
1358 value = of_match_populate(&%(var_name)s, %(v_name)s, value);
1359 TEST_ASSERT(value != 0);
1360 %(cls)s_%(m_name)s_set(
1361 obj, &%(var_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001362""" % dict(cls=cls, var_name=var_name_map(m_type),
Rich Lanea06d0c32013-03-25 08:52:03 -07001363 m_name=m_name, v_name=loxi_utils.version_to_name(version)))
1364 elif m_type == "of_octets_t":
1365 out.write("""\
1366 value = of_octets_populate(&%(var_name)s, value);
1367 TEST_ASSERT(value != 0);
1368 %(cls)s_%(m_name)s_set(
1369 obj, &%(var_name)s);
1370 if (octets.bytes) {
1371 FREE(octets.data);
1372 }
1373""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1374 else:
1375 sub_cls = m_type[:-2] # Trim _t
1376 out.write("""
1377 %(var_name)s = %(sub_cls)s_new(%(v_name)s);
1378 TEST_ASSERT(%(var_name)s != NULL);
1379 value = %(sub_cls)s_%(v_name)s_populate(
1380 %(var_name)s, value);
1381 TEST_ASSERT(value != 0);
1382 %(cls)s_%(m_name)s_set(
1383 obj, %(var_name)s);
1384 %(sub_cls)s_delete(%(var_name)s);
1385""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1386 var_name=var_name_map(m_type),
1387 v_name=loxi_utils.version_to_name(version)))
1388
1389 out.write("""
1390 return value;
1391}
1392""")
1393
1394 out.write("""
1395/**
1396 * Check all members of an object of type %(cls)s
1397 * populated by the above function
1398 * @param obj Pointer to an object to check
1399 * @param value Starting value for checking
1400 * @returns The value after increments for this object's values
1401 */
1402
1403int
1404%(cls)s_%(v_name)s_check(
1405 %(cls)s_t *obj, int value)
1406{
1407""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1408 members, member_types = loxi_utils.all_member_types_get(cls, version)
1409 for m_type in member_types:
1410 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1411 continue
1412 if loxi_utils.type_is_of_object(m_type):
1413 continue
1414 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1415 out.write("""
1416 value = %(cls)s_%(v_name)s_check_scalars(
1417 obj, value);
1418 TEST_ASSERT(value != 0);
1419""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1420
1421 for member in members:
1422 m_type = member["m_type"]
1423 m_name = member["name"]
1424 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1425 continue
1426 if loxi_utils.skip_member_name(m_name):
1427 continue
1428 if m_type == "of_match_t":
1429 out.write("""\
1430 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1431 value = of_match_check(&%(var_name)s, %(v_name)s, value);
1432""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1433 v_name=loxi_utils.version_to_name(version)))
1434 elif m_type == "of_octets_t":
1435 out.write("""\
1436 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1437 value = of_octets_check(&%(var_name)s, value);
1438""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1439 v_name=loxi_utils.version_to_name(version)))
1440 else:
1441 sub_cls = m_type[:-2] # Trim _t
1442 out.write("""
1443 { /* Use get/delete to access on check */
1444 %(m_type)s *%(m_name)s_ptr;
1445
1446 %(m_name)s_ptr = %(cls)s_%(m_name)s_get(obj);
1447 TEST_ASSERT(%(m_name)s_ptr != NULL);
1448 value = %(sub_cls)s_%(v_name)s_check(
1449 %(m_name)s_ptr, value);
1450 TEST_ASSERT(value != 0);
1451 %(sub_cls)s_delete(%(m_name)s_ptr);
1452 }
1453""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1454 var_name=var_name_map(m_type),
1455 v_name=loxi_utils.version_to_name(version)))
1456
1457 out.write("""
1458 /* We shoehorn a test of the dup functions here */
1459 {
1460 %(cls)s_t *dup;
1461
1462 TEST_ASSERT((dup = %(cls)s_dup(obj)) != NULL);
1463 TEST_ASSERT(dup->length == obj->length);
1464 TEST_ASSERT(dup->object_id == obj->object_id);
1465 TEST_ASSERT(dup->version == obj->version);
1466 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1467 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1468 of_object_delete((of_object_t *)dup);
1469
1470 /* And now for the generic dup function */
1471 TEST_ASSERT((dup = (%(cls)s_t *)
1472 of_object_dup(obj)) != NULL);
1473 TEST_ASSERT(dup->length == obj->length);
1474 TEST_ASSERT(dup->object_id == obj->object_id);
1475 TEST_ASSERT(dup->version == obj->version);
1476 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1477 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1478 of_object_delete((of_object_t *)dup);
1479 }
1480
1481 return value;
1482}
1483""" % dict(cls=cls))
1484
1485def unified_accessor_test_case(out, cls, version):
1486 """
1487 Generate one test case for the given version and class
1488 """
1489
1490 members, member_types = scalar_member_types_get(cls, version)
1491 length = of_g.base_length[(cls, version)]
1492 v_name = loxi_utils.version_to_name(version)
1493
1494 out.write("""
1495static int
1496test_%(cls)s_%(v_name)s(void)
1497{
1498 %(cls)s_t *obj;
1499 obj = %(cls)s_new(%(v_name)s);
1500 TEST_ASSERT(obj != NULL);
1501 TEST_ASSERT(obj->version == %(v_name)s);
1502 TEST_ASSERT(obj->length == %(length)d);
1503 TEST_ASSERT(obj->parent == NULL);
1504 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001505""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001506 v_name=v_name, length=length, version=version))
1507 if (not type_maps.class_is_virtual(cls)) or loxi_utils.class_is_list(cls):
1508 out.write("""
1509 if (obj->wire_length_get != NULL) {
1510 int length;
1511
1512 obj->wire_length_get((of_object_t *)obj, &length);
1513 TEST_ASSERT(length == %(length)d);
1514 }
1515 if (obj->wire_type_get != NULL) {
1516 of_object_id_t obj_id;
1517
1518 obj->wire_type_get((of_object_t *)obj, &obj_id);
1519 TEST_ASSERT(obj_id == %(u_cls)s);
1520 }
1521
1522 /* Set up incrementing values for members */
1523 TEST_ASSERT(%(cls)s_%(v_name)s_populate(
1524 obj, 1) != 0);
1525
1526 /* Check values just set */
1527 TEST_ASSERT(%(cls)s_%(v_name)s_check(
1528 obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001529""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001530 v_name=v_name, length=length, version=version))
1531
1532 out.write("""
1533 %(cls)s_delete(obj);
1534
1535 /* To do: Check memory */
1536 return TEST_PASS;
1537}
1538""" % dict(cls=cls))
1539
1540
1541def gen_unified_accessor_funs(out):
1542 for version in of_g.of_version_range:
1543 for cls in of_g.standard_class_order:
1544 if not loxi_utils.class_in_version(cls, version):
1545 continue
1546 if cls in type_maps.inheritance_map:
1547 continue
1548 elif loxi_utils.class_is_list(cls):
1549 gen_list_setup_check(out, cls, version)
1550 else:
1551 gen_class_setup_check(out, cls, version)
1552
1553def gen_unified_accessor_tests(out, name):
1554 loxi_utils.gen_c_copy_license(out)
1555 out.write("""
1556/**
1557 *
1558 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1559 *
1560 * Unified simple class instantiation tests for all versions
1561 */
1562
1563#include <locitest/test_common.h>
1564""")
1565 for version in of_g.of_version_range:
1566 for cls in of_g.standard_class_order:
1567 if not loxi_utils.class_in_version(cls, version):
1568 continue
1569 if cls in type_maps.inheritance_map:
1570 continue
1571 unified_accessor_test_case(out, cls, version)
1572
1573 out.write("""
1574int
1575run_unified_accessor_tests(void)
1576{
1577""")
1578 for version in of_g.of_version_range:
1579 v_name = loxi_utils.version_to_name(version)
1580 for cls in of_g.standard_class_order:
1581 if not loxi_utils.class_in_version(cls, version):
1582 continue
1583 if cls in type_maps.inheritance_map:
1584 continue
1585 test_name = "%s_%s" % (cls, v_name)
1586 out.write(" RUN_TEST(%s);\n" % test_name)
1587
1588 out.write(" return TEST_PASS;\n}\n");
1589
1590
1591
1592################################################################
1593#
1594# Object duplication functions
1595#
1596# These exercise the accessors to create duplicate objects.
1597# They are used in the LOCI test shim which sits in an OF
1598# protocol stream.
1599#
1600# TODO
1601# Resolve version stuff
1602# Complete list dup
1603
1604def gen_dup_list(out, cls, version):
1605 ver_name = loxi_utils.version_to_name(version)
1606 elt_type = loxi_utils.list_to_entry_type(cls)
1607 out.write("""
1608/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001609 * Duplicate a list of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001610 * using accessor functions
1611 * @param src Pointer to object to be duplicated
1612 * @returns A new object of type %(cls)s.
1613 *
1614 * The caller is responsible for deleting the returned value
1615 */
1616%(cls)s_t *
1617%(cls)s_%(ver_name)s_dup(
1618 %(cls)s_t *src)
1619{
1620 %(elt_type)s_t src_elt;
1621 %(elt_type)s_t *dst_elt;
1622 int rv;
1623 %(cls)s_t *dst;
1624
1625 if ((dst = %(cls)s_new(src->version)) == NULL) {
1626 return NULL;
1627 }
1628""" % dict(elt_type=elt_type, cls=cls, ver_name=ver_name))
1629
1630 out.write("""
1631 %(u_cls)s_ITER(src, &src_elt, rv) {
1632 if ((dst_elt = %(elt_type)s_%(ver_name)s_dup(&src_elt)) == NULL) {
1633 of_object_delete((of_object_t *)dst);
1634 return NULL;
1635 }
1636 _TRY_FREE(%(cls)s_append(dst, dst_elt),
1637 dst, NULL);
1638 of_object_delete((of_object_t *)dst_elt);
1639 }
1640
1641 return dst;
1642}
1643""" % dict(u_cls=cls.upper(), elt_type=elt_type, cls=cls, ver_name=ver_name))
1644
1645
1646def gen_dup_inheritance(out, cls, version):
1647 ver_name = loxi_utils.version_to_name(version)
1648 out.write("""
1649/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001650 * Duplicate a super class object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001651 * @param src Pointer to object to be duplicated
1652 * @returns A new object of type %(cls)s.
1653 *
1654 * The caller is responsible for deleting the returned value
1655 */
1656%(cls)s_t *
1657%(cls)s_%(ver_name)s_dup(
1658 %(cls)s_t *src)
1659{
1660""" % dict(cls=cls, ver_name=ver_name))
1661
1662 # For each subclass, check if this is an instance of that subclass
1663 version_classes = type_maps.inheritance_data[cls][version]
1664 for sub_cls in version_classes:
1665 sub_enum = (cls + "_" + sub_cls).upper()
1666 out.write("""
1667 if (src->header.object_id == %(sub_enum)s) {
1668 return (%(cls)s_t *)%(cls)s_%(sub_cls)s_%(ver_name)s_dup(
1669 &src->%(sub_cls)s);
1670 }
1671""" % dict(sub_cls=sub_cls, ver_name=ver_name, sub_enum=sub_enum, cls=cls))
1672
1673 out.write("""
1674 return NULL;
1675}
1676""")
1677
1678
1679def gen_dup_cls(out, cls, version):
1680 """
1681 Generate duplication routine for class cls
1682 """
1683 ver_name = loxi_utils.version_to_name(version)
1684
1685 out.write("""
1686/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001687 * Duplicate an object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001688 * using accessor functions
1689 * @param src Pointer to object to be duplicated
1690 * @returns A new object of type %(cls)s.
1691 *
1692 * The caller is responsible for deleting the returned value
1693 */
1694%(cls)s_t *
1695%(cls)s_%(ver_name)s_dup(
1696 %(cls)s_t *src)
1697{
1698 %(cls)s_t *dst;
1699""" % dict(cls=cls, ver_name=ver_name))
1700
1701 # Get members and types for the class
1702 members, member_types = loxi_utils.all_member_types_get(cls, version)
1703
1704 # Add declarations for each member type
1705 for m_type in member_types:
1706 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1707 # Declare instance of these
1708 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1709 else:
1710 out.write("""
1711 %(m_type)s src_%(v_name)s;
1712 %(m_type)s *dst_%(v_name)s;
1713""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
1714
1715 out.write("""
1716 if ((dst = %(cls)s_new(src->version)) == NULL) {
1717 return NULL;
1718 }
1719""" % dict(cls=cls))
1720
1721 for member in members:
1722 m_type = member["m_type"]
1723 m_name = member["name"]
1724 if loxi_utils.skip_member_name(m_name):
1725 continue
1726 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1727 out.write("""
1728 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1729 %(cls)s_%(m_name)s_set(dst, %(v_name)s);
1730""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1731 elif m_type in ["of_match_t", "of_octets_t"]:
1732 out.write("""
1733 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1734 %(cls)s_%(m_name)s_set(dst, &%(v_name)s);
1735""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1736 else:
1737 sub_cls = m_type[:-2] # Trim _t
1738 out.write("""
1739 %(cls)s_%(m_name)s_bind(
1740 src, &src_%(v_name)s);
1741 dst_%(v_name)s = %(sub_cls)s_%(ver_name)s_dup(&src_%(v_name)s);
1742 if (dst_%(v_name)s == NULL) {
1743 %(cls)s_delete(dst);
1744 return NULL;
1745 }
1746 %(cls)s_%(m_name)s_set(dst, dst_%(v_name)s);
1747 %(sub_cls)s_delete(dst_%(v_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001748""" % dict(sub_cls=sub_cls, cls=cls, m_name=m_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001749 v_name=var_name_map(m_type), ver_name=ver_name))
1750
1751 out.write("""
1752 return dst;
1753}
1754""")
1755
1756def gen_version_dup(out=sys.stdout):
1757 """
1758 Generate duplication routines for each object type
1759 """
1760 out.write("""
1761/* Special try macro for duplicating */
1762#define _TRY_FREE(op, obj, rv) do { \\
1763 int _rv; \\
1764 if ((_rv = (op)) < 0) { \\
1765 LOCI_LOG_ERROR("ERROR %d at %s:%d\\n", _rv, __FILE__, __LINE__); \\
1766 of_object_delete((of_object_t *)(obj)); \\
1767 return (rv); \\
1768 } \\
1769 } while (0)
1770""")
1771
1772 for version in of_g.of_version_range:
1773 for cls in of_g.standard_class_order:
1774 if not loxi_utils.class_in_version(cls, version):
1775 continue
1776 if cls in type_maps.inheritance_map:
1777 gen_dup_inheritance(out, cls, version)
1778 elif loxi_utils.class_is_list(cls):
1779 gen_dup_list(out, cls, version)
1780 else:
1781 gen_dup_cls(out, cls, version)
1782
1783def gen_dup(out=sys.stdout):
1784 """
1785 Generate non-version specific duplication routines for each object type
1786 """
1787
1788 for cls in of_g.standard_class_order:
1789 out.write("""
1790%(cls)s_t *
1791%(cls)s_dup(
1792 %(cls)s_t *src)
1793{
1794""" % dict(cls=cls))
1795 for version in of_g.of_version_range:
1796 if not loxi_utils.class_in_version(cls, version):
1797 continue
1798 hdr = "header." if cls in type_maps.inheritance_map else ""
1799
1800 ver_name = loxi_utils.version_to_name(version)
1801 out.write("""
1802 if (src->%(hdr)sversion == %(ver_name)s) {
1803 return %(cls)s_%(ver_name)s_dup(src);
1804 }
1805""" % dict(cls=cls, ver_name=ver_name, hdr=hdr))
1806
1807 out.write("""
1808 /* Class not supported in given version */
1809 return NULL;
1810}
1811""")
1812
1813def dup_c_gen(out, name):
1814 """
1815 Generate the C file for duplication functions
1816 """
1817 loxi_utils.gen_c_copy_license(out)
1818 out.write("""\
1819/*
1820 * Duplication functions for all OF objects
1821 *
1822 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1823 *
1824 * These are test functions for exercising accessors. You can call
1825 * of_object_dup for an efficient duplication.
1826 */
1827
1828#define DISABLE_WARN_UNUSED_RESULT
1829#include "loci_log.h"
1830#include <locitest/of_dup.h>
1831
1832""")
1833
1834 gen_version_dup(out)
1835 gen_dup(out)
1836
1837
1838def dup_h_gen(out, name):
1839 """
1840 Generate the header file for duplication functions
1841 """
1842
1843 loxi_utils.gen_c_copy_license(out)
1844 out.write("""
1845/*
1846 * Duplication function header file
1847 *
1848 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1849 */
1850
1851#if !defined(_OF_DUP_H_)
1852#define _OF_DUP_H_
1853
1854#include <loci/loci.h>
1855""")
1856
1857 for cls in of_g.standard_class_order:
1858 out.write("""
1859extern %(cls)s_t *
1860 %(cls)s_dup(
1861 %(cls)s_t *src);
1862""" % dict(cls=cls))
1863
1864 for version in of_g.of_version_range:
1865 for cls in of_g.standard_class_order:
1866 if not loxi_utils.class_in_version(cls, version):
1867 continue
1868 ver_name = loxi_utils.version_to_name(version)
1869 out.write("""
1870extern %(cls)s_t *
1871 %(cls)s_%(ver_name)s_dup(
1872 %(cls)s_t *src);
1873""" % dict(cls=cls, ver_name=ver_name))
1874
1875 out.write("\n#endif /* _OF_DUP_H_ */\n")
1876
1877def gen_log_test(out):
1878 """
1879 Generate test for obj log calls
1880
1881 Define a trivial handler for object logging; call all obj log fns
1882 """
1883 out.write("""
1884
1885/**
1886 * Test object dump functions
1887 */
1888
1889int
1890test_dump_objs(void)
1891{
1892 of_object_t *obj;
1893
1894 FILE *out = fopen("/dev/null", "w");
1895
1896 /* Call each obj dump function */
1897""")
1898 for version in of_g.of_version_range:
1899 for j, cls in enumerate(of_g.all_class_order):
1900 if not loxi_utils.class_in_version(cls, version):
1901 continue
1902 if cls in type_maps.inheritance_map:
1903 continue
1904 out.write("""
1905 obj = (of_object_t *)%(cls)s_new(%(version)s);
1906 of_object_dump((loci_writer_f)fprintf, out, obj);
1907 of_object_delete(obj);
1908""" % dict(cls=cls, version=of_g.of_version_wire2name[version]))
Andreas Wundsam53256162013-05-02 14:05:53 -07001909
Rich Lanea06d0c32013-03-25 08:52:03 -07001910 out.write("""
1911 fclose(out);
1912 return TEST_PASS;
1913}
1914""")
1915
1916def gen_ident_tests(out):
1917 """
1918 Generate tests for identifiers
1919
1920 For all idents, instantiate, test version supported macros
1921 For flags, set it, test it, clear it, test it.
1922 """
1923 out.write("""
1924/**
1925 * Test cases for all flag accessor macros
1926 * These only test self consistency (and that they compile)
1927 */
1928int
1929test_ident_macros(void)
1930{
1931 int value __attribute__((unused));
1932 uint32_t flags;
1933
1934""")
1935
1936 for ident, info in of_g.identifiers.items():
1937 if not identifiers.defined_versions_agree(of_g.identifiers,
1938 of_g.target_version_list,
1939 ident):
1940 # @fixme
1941 continue
1942 out.write(" value = %s;\n" % ident)
1943 for version in of_g.target_version_list:
1944 if version in info["values_by_version"].keys():
1945 out.write(" TEST_ASSERT(%s_SUPPORTED(%s));\n" %
1946 (ident, of_g.of_version_wire2name[version]))
1947 else:
1948 out.write(" TEST_ASSERT(!%s_SUPPORTED(%s));\n" %
1949 (ident, of_g.of_version_wire2name[version]))
1950 if flags.ident_is_flag(ident):
1951 # Grab first supported version
1952 for version in info["values_by_version"]:
1953 break
1954 out.write("""
1955 flags = 0;
1956 %(ident)s_SET(flags, %(ver_name)s);
1957 TEST_ASSERT(flags == %(ident)s_BY_VERSION(%(ver_name)s));
1958 TEST_ASSERT(%(ident)s_TEST(flags, %(ver_name)s));
1959 %(ident)s_CLEAR(flags, %(ver_name)s);
1960 TEST_ASSERT(flags == 0);
1961 TEST_ASSERT(!%(ident)s_TEST(flags, %(ver_name)s));
1962""" % dict(ident=ident, ver_name=of_g.of_version_wire2name[version]))
1963
1964 out.write("""
1965 return TEST_PASS;
1966}
1967""")
1968