blob: fab9f969b808dc18c5b9520f0e91f412980b567f [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
Rich Laneccae0312013-07-21 23:34:13 -070069import util
70import test_data
Rich Lanea06d0c32013-03-25 08:52:03 -070071
72def var_name_map(m_type):
73 """
74 Map a type to a generic variable name for the type.
75 @param m_type The data type
76
77 Used mostly in test code generation, but also for the dup functions.
78 """
79 _var_name_map= dict(
80 uint8_t="val8",
81 uint16_t="val16",
82 uint32_t="val32",
83 uint64_t="val64",
Andreas Wundsamb566a162013-07-18 19:30:23 -070084 of_ipv4_t="ipv4",
Rich Lanea06d0c32013-03-25 08:52:03 -070085 of_port_no_t="port_no",
86 of_fm_cmd_t="fm_cmd",
87 of_wc_bmap_t="wc_bmap",
88 of_match_bmap_t = "match_bmap",
Andreas Wundsam53256162013-05-02 14:05:53 -070089 of_port_name_t="port_name",
Rich Lanea06d0c32013-03-25 08:52:03 -070090 of_table_name_t="table_name",
91 of_desc_str_t="desc_str",
Andreas Wundsam53256162013-05-02 14:05:53 -070092 of_serial_num_t="ser_num",
93 of_mac_addr_t="mac_addr",
Rich Lanea06d0c32013-03-25 08:52:03 -070094 of_ipv6_t="ipv6",
95 # Non-scalars; more TBD
96 of_octets_t="octets",
97 of_meter_features_t="features",
Dan Talaycoc0e802e2013-05-18 23:52:39 -070098 of_match_t="match",
99 # BSN extensions
100 of_bsn_vport_q_in_q_t="vport",
101 )
Rich Lanea06d0c32013-03-25 08:52:03 -0700102
103 if m_type.find("of_list_") == 0:
104 return "list"
105 if m_type in of_g.of_mixed_types:
106 return of_g.of_mixed_types[m_type]["short_name"]
107 return _var_name_map[m_type]
108
109integer_types = ["uint8_t", "uint16_t", "uint32_t", "uint64_t",
110 "of_port_no_t", "of_fm_cmd_t", "of_wc_bmap_t",
Andreas Wundsamb566a162013-07-18 19:30:23 -0700111 "of_match_bmap_t", "of_ipv4_t"]
Rich Lanea06d0c32013-03-25 08:52:03 -0700112string_types = [ "of_port_name_t", "of_table_name_t",
Andreas Wundsam53256162013-05-02 14:05:53 -0700113 "of_desc_str_t", "of_serial_num_t", "of_mac_addr_t",
Rich Lanea06d0c32013-03-25 08:52:03 -0700114 "of_ipv6_t"]
115
116scalar_types = integer_types[:]
117scalar_types.extend(string_types)
118
119def ignore_member(cls, version, m_name, m_type):
120 """
121 Filter out names or types that either don't have accessors
122 or those that should not be messed with
123 or whose types we're not ready to deal with yet.
124 """
125 # This will probably need more granularity as more extensions are added
126 if (type_maps.class_is_extension(cls, version) and (
127 m_name == "experimenter" or
128 m_name == "subtype")):
129 return True
130 return loxi_utils.skip_member_name(m_name) or m_type not in scalar_types
131
132def gen_fill_string(out):
133 out.write("""
134
135/**
136 * The increment to use on values inside a string
137 */
138#define OF_TEST_STR_INCR 3
139
140/**
141 * Fill in a buffer with incrementing values starting
142 * at the given offset with the given value
143 * @param buf The buffer to fill
144 * @param value The value to use for data
145 * @param len The number of bytes to fill
146 */
147
148void
149of_test_str_fill(uint8_t *buf, int value, int len)
150{
151 int i;
152
153 for (i = 0; i < len; i++) {
154 *buf = value;
155 value += OF_TEST_STR_INCR;
156 buf++;
157 }
158}
159
160/**
161 * Given a buffer, verify that it's filled as above
162 * @param buf The buffer to check
163 * @param value The value to use for data
164 * @param len The number of bytes to fill
165 * @return Boolean True on equality (success)
166 */
167
168int
169of_test_str_check(uint8_t *buf, int value, int len)
170{
171 int i;
172 uint8_t val8;
173
174 val8 = value;
175
176 for (i = 0; i < len; i++) {
177 if (*buf != val8) {
178 return 0;
179 }
180 val8 += OF_TEST_STR_INCR;
181 buf++;
182 }
183
184 return 1;
185}
186
187/**
188 * Global that determines how octets should be populated
189 * -1 means use value % MAX (below) to determine length
190 * 0, 1, ... means used that fixed length
191 *
192 * Note: Was 16K, but that made objects too big. May add flexibility
193 * to call populate with a max parameter for length
194 */
195int octets_pop_style = -1;
196#define OCTETS_MAX_VALUE (128) /* 16K was too big */
197#define OCTETS_MULTIPLIER 6367 /* A prime */
198
199int
200of_octets_populate(of_octets_t *octets, int value)
201{
202 if (octets_pop_style < 0) {
203 octets->bytes = (value * OCTETS_MULTIPLIER) % OCTETS_MAX_VALUE;
204 } else {
205 octets->bytes = octets_pop_style;
206 }
207
208 if (octets->bytes != 0) {
209 if ((octets->data = (uint8_t *)MALLOC(octets->bytes)) == NULL) {
210 return 0;
211 }
212 of_test_str_fill(octets->data, value, octets->bytes);
213 value += 1;
214 }
215
216 return value;
217}
218
219int
220of_octets_check(of_octets_t *octets, int value)
221{
222 int len;
223
224 if (octets_pop_style < 0) {
225 len = (value * OCTETS_MULTIPLIER) % OCTETS_MAX_VALUE;
226 TEST_ASSERT(octets->bytes == len);
227 } else {
228 TEST_ASSERT(octets->bytes == octets_pop_style);
229 }
230
231 if (octets->bytes != 0) {
232 TEST_ASSERT(of_test_str_check(octets->data, value, octets->bytes)
233 == 1);
234 value += 1;
235 }
236
237 return value;
238}
239
240int
241of_match_populate(of_match_t *match, of_version_t version, int value)
242{
243 MEMSET(match, 0, sizeof(*match));
244 match->version = version;
245""")
246
247 for key, entry in match.of_match_members.items():
248 out.write("""
Andreas Wundsam53256162013-05-02 14:05:53 -0700249 if (!(of_match_incompat[version] &
Rich Lanea06d0c32013-03-25 08:52:03 -0700250 OF_OXM_BIT(OF_OXM_INDEX_%(ku)s))) {
251 OF_MATCH_MASK_%(ku)s_EXACT_SET(match);
252 VAR_%(u_type)s_INIT(match->fields.%(key)s, value);
253 value += 1;
254 }
255
256""" % dict(key=key, u_type=entry["m_type"].upper(), ku=key.upper()))
257
258 out.write("""
259 if (value % 2) {
260 /* Sometimes set ipv4 addr masks to non-exact */
261 match->masks.ipv4_src = 0xffff0000;
262 match->masks.ipv4_dst = 0xfffff800;
263 }
Dan Talaycofb50d382013-08-05 16:00:17 -0700264
265 /* Restrict values according to masks */
266 of_match_values_mask(match);
Rich Lanea06d0c32013-03-25 08:52:03 -0700267 return value;
268}
269
270int
271of_match_check(of_match_t *match, of_version_t version, int value)
272{
273 of_match_t check;
274
275 value = of_match_populate(&check, match->version, value);
276 TEST_ASSERT(value != 0);
277 TEST_ASSERT(MEMCMP(match, &check, sizeof(check)) == 0);
278
279 return value;
280}
281""")
282
283def gen_common_test_header(out, name):
284 loxi_utils.gen_c_copy_license(out)
285 out.write("""
286/*
287 * Test header file
288 *
289 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
290 */
291
292#if !defined(_TEST_COMMON_H_)
293#define _TEST_COMMON_H_
294
295#define DISABLE_WARN_UNUSED_RESULT
296#include <loci/loci.h>
297#include <locitest/of_dup.h>
298#include <locitest/unittest.h>
299
300extern int global_error;
301extern int exit_on_error;
302
303/* @todo Make option for -k to continue tests if errors */
304#define RUN_TEST(test) do { \\
305 int rv; \\
306 TESTCASE(test, rv); \\
307 if (rv != TEST_PASS) { \\
308 global_error=1; \\
309 if (exit_on_error) return(1); \\
310 } \\
311 } while(0)
312
313#define TEST_OK(op) TEST_ASSERT((op) == OF_ERROR_NONE)
314#define TEST_INDIGO_OK(op) TEST_ASSERT((op) == INDIGO_ERROR_NONE)
315
316/*
317 * Declarations of functions to populate scalar values in a a class
318 */
319
320extern void of_test_str_fill(uint8_t *buf, int value, int len);
321extern int of_test_str_check(uint8_t *buf, int value, int len);
322
323
324extern int of_octets_populate(of_octets_t *octets, int value);
325extern int of_octets_check(of_octets_t *octets, int value);
326extern int of_match_populate(of_match_t *match, of_version_t version,
327 int value);
328extern int of_match_check(of_match_t *match, of_version_t version, int value);
329extern int test_ident_macros(void);
330extern int test_dump_objs(void);
331
332/* In test_match_utils.c */
333extern int test_match_utils(void);
334
335extern int run_unified_accessor_tests(void);
336extern int run_match_tests(void);
337extern int run_utility_tests(void);
338
339extern int run_scalar_acc_tests(void);
340extern int run_list_tests(void);
341extern int run_message_tests(void);
342extern int run_setup_from_add_tests(void);
343
344extern int run_validator_tests(void);
345
346extern int run_list_limits_tests(void);
347
348extern int test_ext_objs(void);
Rich Laneccae0312013-07-21 23:34:13 -0700349extern int test_datafiles(void);
Rich Lanea06d0c32013-03-25 08:52:03 -0700350
351""")
352
353 for version in of_g.of_version_range:
354 for cls in of_g.standard_class_order:
355 if not loxi_utils.class_in_version(cls, version):
356 continue
357 if cls in type_maps.inheritance_map:
358 continue
359 out.write("""
360extern int %(cls)s_%(v_name)s_populate(
361 %(cls)s_t *obj, int value);
362extern int %(cls)s_%(v_name)s_check(
363 %(cls)s_t *obj, int value);
364extern int %(cls)s_%(v_name)s_populate_scalars(
365 %(cls)s_t *obj, int value);
366extern int %(cls)s_%(v_name)s_check_scalars(
367 %(cls)s_t *obj, int value);
368""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
369
370 out.write("""
371/*
372 * Declarations for list population and check primitives
373 */
374""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700375
Rich Lanea06d0c32013-03-25 08:52:03 -0700376 for version in of_g.of_version_range:
377 for cls in of_g.ordered_list_objects:
378 if cls in type_maps.inheritance_map:
379 continue
380
381 if version in of_g.unified[cls]:
382 out.write("""
383extern int
384 list_setup_%(cls)s_%(v_name)s(
385 %(cls)s_t *list, int value);
386extern int
387 list_check_%(cls)s_%(v_name)s(
388 %(cls)s_t *list, int value);
389""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
390
391 out.write("\n#endif /* _TEST_COMMON_H_ */\n")
392
393def gen_common_test(out, name):
394 """
395 Generate common test content including main
396 """
397 loxi_utils.gen_c_copy_license(out)
398 out.write("""
399/*
400 * Common test code for LOCI
401 *
402 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
403 */
404
405#define DISABLE_WARN_UNUSED_RESULT
406#include "loci_log.h"
407#include <loci/loci_obj_dump.h>
408#include <locitest/unittest.h>
409#include <locitest/test_common.h>
410
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900411/* mcheck is a glibc extension */
412#if defined(__linux__)
Rich Lanea06d0c32013-03-25 08:52:03 -0700413#include <mcheck.h>
414#define MCHECK_INIT mcheck(NULL)
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900415#else
Rich Lanea06d0c32013-03-25 08:52:03 -0700416#define MCHECK_INIT do { } while (0)
417#endif
418
419/**
420 * Exit on error if set to 1
421 */
422int exit_on_error = 1;
423
424/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700425 * Global error state: 0 is okay, 1 is error
Rich Lanea06d0c32013-03-25 08:52:03 -0700426 */
427int global_error = 0;
428
429extern int run_unified_accessor_tests(void);
430extern int run_match_tests(void);
431extern int run_utility_tests(void);
432
433extern int run_scalar_acc_tests(void);
434extern int run_list_tests(void);
435extern int run_message_tests(void);
436
437/**
438 * Macros for initializing and checking scalar types
439 *
440 * @param var The variable being initialized or checked
441 * @param val The integer value to set/check against, see below
442 *
443 * Note that equality means something special for strings. Each byte
444 * is initialized to an incrementing value. So check is done against that.
445 *
446 */
447
448""")
449 for t in scalar_types:
450 if t in integer_types:
451 out.write("""
452#define VAR_%s_INIT(var, val) var = (%s)(val)
453#define VAR_%s_CHECK(var, val) ((var) == (%s)(val))
454""" % (t.upper(), t, t.upper(), t))
455 else:
456 out.write("""
457#define VAR_%s_INIT(var, val) \\
458 of_test_str_fill((uint8_t *)&(var), val, sizeof(var))
459#define VAR_%s_CHECK(var, val) \\
460 of_test_str_check((uint8_t *)&(var), val, sizeof(var))
461""" % (t.upper(), t.upper()))
462
463 gen_fill_string(out)
464 gen_scalar_set_check_funs(out)
465 gen_list_set_check_funs(out)
466 gen_unified_accessor_funs(out)
467
468 gen_ident_tests(out)
469 gen_log_test(out)
470
471def gen_message_scalar_test(out, name):
472 """
473 Generate test cases for message objects, scalar accessors
474 """
475
476 loxi_utils.gen_c_copy_license(out)
477 out.write("""
478/**
479 *
480 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
481 *
482 * Message-scalar tests for all versions
483 */
484
485#include <locitest/test_common.h>
486""")
487 for version in of_g.of_version_range:
488 v_name = loxi_utils.version_to_name(version)
489 out.write("""
490/**
491 * Message-scalar tests for version %s
492 */
493""" % v_name)
494 for cls in of_g.standard_class_order:
495 if cls in type_maps.inheritance_map:
496 continue
497 if version in of_g.unified[cls]:
498 message_scalar_test(out, version, cls)
499
500 out.write("""
501int
502run_scalar_acc_tests(void)
503{
504""")
505 for version in of_g.of_version_range:
506 v_name = loxi_utils.version_to_name(version)
507 for cls in of_g.standard_class_order:
508 if cls in type_maps.inheritance_map:
509 continue
510 if version in of_g.unified[cls]:
511 test_name = "%s_%s" % (cls, v_name)
512 out.write(" RUN_TEST(%s_scalar);\n" % test_name)
513
514 out.write(" return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -0700515
Rich Lanea06d0c32013-03-25 08:52:03 -0700516def message_scalar_test(out, version, cls):
517 """
518 Generate one test case for the given version and class
519 """
520
521 members, member_types = scalar_member_types_get(cls, version)
Rich Lanef70be942013-07-18 13:33:14 -0700522 length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -0700523 v_name = loxi_utils.version_to_name(version)
524
525 out.write("""
526static int
527test_%(cls)s_%(v_name)s_scalar(void)
528{
529 %(cls)s_t *obj;
530
531 obj = %(cls)s_new(%(v_name)s);
532 TEST_ASSERT(obj != NULL);
533 TEST_ASSERT(obj->version == %(v_name)s);
534 TEST_ASSERT(obj->length == %(length)d);
535 TEST_ASSERT(obj->parent == NULL);
536 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -0700537""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700538 v_name=v_name, length=length, version=version))
539 if not type_maps.class_is_virtual(cls):
540 out.write("""
541 if (obj->wire_length_get != NULL) {
542 int length;
543
544 obj->wire_length_get((of_object_t *)obj, &length);
545 TEST_ASSERT(length == %(length)d);
546 }
547
548 /* Set up incrementing values for scalar members */
549 %(cls)s_%(v_name)s_populate_scalars(obj, 1);
550
551 /* Check values just set */
552 TEST_ASSERT(%(cls)s_%(v_name)s_check_scalars(obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700553""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700554 v_name=v_name, length=length, version=version))
555
556 out.write("""
557 %(cls)s_delete(obj);
558
559 /* To do: Check memory */
560 return TEST_PASS;
561}
562""" % dict(cls=cls))
563
564# Get the members and list of scalar types for members of a given class
565def scalar_member_types_get(cls, version):
566 member_types = []
567
568 if not version in of_g.unified[cls]:
569 return ([], [])
570
571 if "use_version" in of_g.unified[cls][version]:
572 v = of_g.unified[cls][version]["use_version"]
573 members = of_g.unified[cls][v]["members"]
574 else:
575 members = of_g.unified[cls][version]["members"]
576 # Accumulate variables that are supported
577 for member in members:
578 m_type = member["m_type"]
579 m_name = member["name"]
Andreas Wundsam53256162013-05-02 14:05:53 -0700580 if (not loxi_utils.type_is_scalar(m_type) or
Rich Lanea06d0c32013-03-25 08:52:03 -0700581 ignore_member(cls, version, m_name, m_type)):
582 continue
583 if not m_type in member_types:
584 member_types.append(m_type)
585
586 return (members, member_types)
587
588def scalar_funs_instance(out, cls, version, members, member_types):
589 """
590 Generate one instance of scalar set/check functions
591 """
592 out.write("""
593/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700594 * Populate the scalar values in obj of type %(cls)s,
595 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700596 * @param obj Pointer to an object to populate
597 * @param value The seed value to use in populating the object
598 * @returns The value after increments for this object's values
599 */
600int %(cls)s_%(v_name)s_populate_scalars(
601 %(cls)s_t *obj, int value) {
602""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
603 # Declare string types
604 for t in member_types:
605 out.write(" %s %s;\n" % (t, var_name_map(t)))
606 for member in members:
607 m_type = member["m_type"]
608 m_name = member["name"]
609 if (not loxi_utils.type_is_scalar(m_type) or
610 ignore_member(cls, version, m_name, m_type)):
611 continue
612 v_name = var_name_map(m_type);
613 out.write("""
614 VAR_%(u_type)s_INIT(%(v_name)s, value);
615 %(cls)s_%(m_name)s_set(obj, %(v_name)s);
616 value += 1;
617""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
618 out.write("""
619 return value;
620}
621""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700622
Rich Lanea06d0c32013-03-25 08:52:03 -0700623 out.write("""
624/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700625 * Check scalar values in obj of type %(cls)s,
626 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700627 * @param obj Pointer to an object to check
628 * @param value Starting value for checking
629 * @returns The value after increments for this object's values
630 */
631int %(cls)s_%(v_name)s_check_scalars(
632 %(cls)s_t *obj, int value) {
633""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
634
635 for t in member_types:
636 out.write(" %s %s;\n" % (t, var_name_map(t)))
637 for member in members:
638 m_type = member["m_type"]
639 m_name = member["name"]
640 if (not loxi_utils.type_is_scalar(m_type) or
641 ignore_member(cls, version, m_name, m_type)):
642 continue
643 v_name = var_name_map(m_type);
644 out.write("""
645 %(cls)s_%(m_name)s_get(obj, &%(v_name)s);
646 TEST_ASSERT(VAR_%(u_type)s_CHECK(%(v_name)s, value));
647 value += 1;
648""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
649
650 out.write("""
651 return value;
652}
653
654""")
655
656def gen_scalar_set_check_funs(out):
657 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700658 For each object class with scalar members, generate functions that
Rich Lanea06d0c32013-03-25 08:52:03 -0700659 set and check their values
660 """
661 for version in of_g.of_version_range:
662 for cls in of_g.standard_class_order:
663 (members, member_types) = scalar_member_types_get(cls, version)
664 scalar_funs_instance(out, cls, version, members, member_types)
665
666
667# Helper function to set up a subclass instance for a test
668def setup_instance(out, cls, subcls, instance, v_name, inst_len, version):
669 base_type = loxi_utils.list_to_entry_type(cls)
670 setup_template = """
671 %(subcls)s_init(%(inst)s, %(v_name)s, -1, 1);
Andreas Wundsam53256162013-05-02 14:05:53 -0700672 %(cls)s_append_bind(list,
Rich Lanea06d0c32013-03-25 08:52:03 -0700673 (%(base_type)s_t *)%(inst)s);
674 value = %(subcls)s_%(v_name)s_populate(
675 %(inst)s, value);
676 cur_len += %(inst)s->length;
677 TEST_ASSERT(list->length == cur_len);
678"""
679 out.write("""
680 /* Append two instances of type %s */
681""" % subcls)
682 for i in range(2):
683 out.write(setup_template %
Andreas Wundsam53256162013-05-02 14:05:53 -0700684 dict(inst=instance, subcls=subcls, v_name=v_name,
685 base_type=base_type, cls=cls, inst_len=inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700686 version=version))
687
688def check_instance(out, cls, subcls, instance, v_name, inst_len, version, last):
689 check_template = ""
690 if inst_len >= 0:
691 check_template = """
692 TEST_ASSERT(%(inst)s->length == %(inst_len)d);
693 if (%(inst)s->wire_length_get != NULL) {
694 int length;
695
696 %(inst)s->wire_length_get(
697 (of_object_t *)&elt, &length);
698 TEST_ASSERT(length == %(inst_len)d);
699 }
700"""
701 check_template += """
702 TEST_ASSERT(%(inst)s->object_id == %(elt_name)s);
703 value = %(subcls)s_%(v_name)s_check(
704 %(inst)s, value);
705 TEST_ASSERT(value != 0);
706"""
707 out.write("\n /* Check two instances of type %s */" % instance)
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 out.write("""\
714 TEST_OK(%(cls)s_next(list, &elt));
715""" % dict(cls=cls))
716
Andreas Wundsam53256162013-05-02 14:05:53 -0700717 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700718 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
719 inst=instance, subcls=subcls,
720 v_name=loxi_utils.version_to_name(version)))
721 if last:
722 out.write("""\
723 TEST_ASSERT(%(cls)s_next(list, &elt) == OF_ERROR_RANGE);
724""" % dict(cls=cls))
725 else:
726 out.write("""\
727 TEST_OK(%(cls)s_next(list, &elt));
728""" % dict(cls=cls))
729
730def setup_list_fn(out, version, cls):
731 """
732 Generate a helper function that populates a list with two
733 of each type of subclass it supports
734 """
735 out.write("""
736/**
737 * Set up a list of type %(cls)s with two of each type of subclass
738 */
739int
740list_setup_%(cls)s_%(v_name)s(
741 %(cls)s_t *list, int value)
742{
743""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
744 base_type = loxi_utils.list_to_entry_type(cls)
745 out.write("""
746 %(base_type)s_t elt;
747 int cur_len = 0;
748""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700749
Rich Lanea06d0c32013-03-25 08:52:03 -0700750 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -0700751 sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
Rich Lanea06d0c32013-03-25 08:52:03 -0700752 v_name = loxi_utils.version_to_name(version)
753
754 if len(sub_classes) == 0:
755 out.write(" /* No subclasses for %s */\n"% base_type)
756 out.write(" %s_t *elt_p;\n" % base_type)
757 out.write("\n elt_p = &elt;\n")
758 else:
759 out.write(" /* Declare pointers for each subclass */\n")
760 for instance, subcls in sub_classes:
761 out.write(" %s_t *%s;\n" % (subcls, instance))
762 out.write("\n /* Instantiate pointers for each subclass */\n")
763 for instance, subcls in sub_classes:
764 out.write(" %s = &elt.%s;\n" % (instance, instance))
765
766 if len(sub_classes) == 0: # No inheritance case
767 inst_len = loxi_utils.base_type_to_length(base_type, version)
768 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
769 else:
770 for instance, subcls in sub_classes:
771 inst_len = of_g.base_length[(subcls, version)]
772 setup_instance(out, cls, subcls, instance, v_name, inst_len, version)
773 out.write("""
774
775 return value;
776}
777""")
778
779def check_list_fn(out, version, cls):
780 """
781 Generate a helper function that checks a list populated by above fn
782 """
783 out.write("""
784/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700785 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -0700786 * list_setup_%(cls)s_%(v_name)s
787 */
788int
789list_check_%(cls)s_%(v_name)s(
790 %(cls)s_t *list, int value)
791{
792""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
793 base_type = loxi_utils.list_to_entry_type(cls)
794 out.write("""
795 %(base_type)s_t elt;
796""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700797
Rich Lanea06d0c32013-03-25 08:52:03 -0700798 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -0700799 sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
Rich Lanea06d0c32013-03-25 08:52:03 -0700800 v_name = loxi_utils.version_to_name(version)
801
802 if len(sub_classes) == 0:
803 out.write(" /* No subclasses for %s */\n"% base_type)
804 out.write(" %s_t *elt_p;\n" % base_type)
805 out.write("\n elt_p = &elt;\n")
806 else:
807 out.write(" /* Declare pointers for each subclass */\n")
808 for instance, subcls in sub_classes:
809 out.write(" %s_t *%s;\n" % (subcls, instance))
810 out.write("\n /* Instantiate pointers for each subclass */\n")
811 for instance, subcls in sub_classes:
812 out.write(" %s = &elt.%s;\n" % (instance, instance))
813
814 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
815 if len(sub_classes) == 0: # No inheritance case
816 if loxi_utils.class_is_var_len(base_type, version):
817 inst_len = -1
818 else:
819 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -0700820 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700821 version, True)
822 else:
823 count = 0
824 for instance, subcls in sub_classes:
825 count += 1
826 if loxi_utils.class_is_var_len(subcls, version):
827 inst_len = -1
828 else:
829 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -0700830 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700831 version, count==len(sub_classes))
832
833 out.write("""
834 return value;
835}
836""" % dict(base_type=base_type))
837
838def gen_list_set_check_funs(out):
839 for version in of_g.of_version_range:
840 for cls in of_g.ordered_list_objects:
841 if cls in type_maps.inheritance_map:
842 continue
843
844 if version in of_g.unified[cls]:
845 setup_list_fn(out, version, cls)
846 check_list_fn(out, version, cls)
847
848# Maybe: Get a map from list class to parent, mem_name of container
849
850def list_test(out, version, cls):
851 out.write("""
852static int
853test_%(cls)s_%(v_name)s(void)
854{
855""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
856 base_type = loxi_utils.list_to_entry_type(cls)
857
858 out.write(""" %(cls)s_t *list;
859 int value = 1;
860""" % dict(cls=cls, base_type=base_type))
861
862 out.write("""
863 list = %(cls)s_new(%(v_name)s);
864 TEST_ASSERT(list != NULL);
865 TEST_ASSERT(list->version == %(v_name)s);
866 TEST_ASSERT(list->length == 0);
867 TEST_ASSERT(list->parent == NULL);
868 TEST_ASSERT(list->object_id == %(enum_cls)s);
869
870 value = list_setup_%(cls)s_%(v_name)s(list, value);
871 TEST_ASSERT(value != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700872""" % dict(cls=cls, base_type=base_type, v_name=loxi_utils.version_to_name(version),
Rich Lanea06d0c32013-03-25 08:52:03 -0700873 enum_cls=loxi_utils.enum_name(cls)))
874
875 out.write("""
876 /* Now check values */
877 value = 1;
878 value = list_check_%(cls)s_%(v_name)s(list, value);
879 TEST_ASSERT(value != 0);
880""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
881
882 out.write("""
883 %(cls)s_delete(list);
884
885 return TEST_PASS;
886}
887""" % dict(cls=cls))
888
889def gen_list_test(out, name):
890 """
891 Generate base line test cases for lists
892 @param out The file handle to write to
893 """
894
895 loxi_utils.gen_c_copy_license(out)
896 out.write("""
897/**
898 *
899 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
900 *
901 * Message-scalar tests for all versions
902 */
903
904#include <locitest/test_common.h>
905""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700906
Rich Lanea06d0c32013-03-25 08:52:03 -0700907 for version in of_g.of_version_range:
908 v_name = loxi_utils.version_to_name(version)
909 out.write("""
910/**
911 * Baseline list tests for version %s
912 */
913""" % v_name)
914 for cls in of_g.ordered_list_objects:
915 if cls in type_maps.inheritance_map:
916 continue
917 if version in of_g.unified[cls]:
918 list_test(out, version, cls)
919
920 out.write("""
921int
922run_list_tests(void)
923{
924""")
925 for version in of_g.of_version_range:
926 v_name = loxi_utils.version_to_name(version)
927 for cls in of_g.ordered_list_objects:
928 if cls in type_maps.inheritance_map:
929 continue
930 if version in of_g.unified[cls]:
931 test_name = "%s_%s" % (cls, v_name)
932 out.write(" RUN_TEST(%s);\n" % test_name)
933
934 out.write("\n return TEST_PASS;\n}\n");
935
936def gen_match_test(out, name):
937 """
938 Generate baseline tests for match functions
939 """
940
941 loxi_utils.gen_c_copy_license(out)
942 out.write("""\
943/**
944 *
945 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
946 *
947 * Message-scalar tests for all versions
948 * @fixme These are mostly hard coded now.
949 */
950
951#include <locitest/test_common.h>
952
953static int
954test_match_1(void)
955{
956 of_match_v1_t *m_v1;
957 of_match_v2_t *m_v2;
958 of_match_v3_t *m_v3;
959 of_match_v4_t *m_v4;
960 of_match_t match;
961 int value = 1;
962 int idx;
963 uint32_t exp_value;
964
965 /* Verify default values for ip mask map */
966 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
967 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
968 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
969 if (idx < 32) {
970 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
971 }
972 }
973
974 TEST_ASSERT(of_ip_mask_map_set(17, 0xabcdef00) == OF_ERROR_NONE);
975 TEST_ASSERT(of_ip_mask_to_index(0xabcdef00) == 17);
976 TEST_ASSERT(of_ip_index_to_mask(17) == 0xabcdef00);
977
978 TEST_ASSERT(of_ip_mask_map_set(62, 0xabcdefff) == OF_ERROR_NONE);
979 TEST_ASSERT(of_ip_mask_to_index(0xabcdefff) == 62);
980 TEST_ASSERT(of_ip_index_to_mask(62) == 0xabcdefff);
981
982 /* Test re-init */
983 of_ip_mask_map_init();
984 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
985 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
986 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
987 if (idx < 32) {
988 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
989 }
990 }
991""")
992
993 for version in of_g.of_version_range:
994 out.write("""
995 /* Create/populate/convert and delete for version %(v_name)s */
996 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
997 TEST_ASSERT(m_v%(version)d != NULL);
998 TEST_ASSERT((value = of_match_populate(&match, %(v_name)s, value)) > 0);
999 TEST_OK(of_match_to_wire_match_v%(version)d(&match, m_v%(version)d));
1000 of_match_v%(version)d_delete(m_v%(version)d);
1001""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1002
1003 out.write("""
1004 return TEST_PASS;
1005}
1006""")
1007
1008 out.write("""
1009static int
1010test_match_2(void)
1011{
1012 of_match_v1_t *m_v1;
1013 of_match_v2_t *m_v2;
1014 of_match_v3_t *m_v3;
1015 of_match_v3_t *m_v4;
1016 of_match_t match1;
1017 of_match_t match2;
1018 int value = 1;
1019""")
1020
1021 for version in of_g.of_version_range:
1022 out.write("""
1023 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
1024 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
1025 TEST_ASSERT(m_v%(version)d != NULL);
1026 TEST_OK(of_match_to_wire_match_v%(version)d(&match1, m_v%(version)d));
1027 TEST_OK(of_match_v%(version)d_to_match(m_v%(version)d, &match2));
1028 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1029 of_match_v%(version)d_delete(m_v%(version)d);
1030""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1031
1032 out.write("""
1033 return TEST_PASS;
1034}
1035""")
1036
1037 out.write("""
1038static int
1039test_match_3(void)
1040{
1041 of_match_t match1;
1042 of_match_t match2;
1043 int value = 1;
1044 of_octets_t octets;
1045""")
1046 for version in of_g.of_version_range:
1047 out.write("""
1048 /* Serialize to version %(v_name)s */
1049 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001050 TEST_ASSERT(of_match_serialize(%(v_name)s, &match1, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001051 OF_ERROR_NONE);
Andreas Wundsam53256162013-05-02 14:05:53 -07001052 TEST_ASSERT(of_match_deserialize(%(v_name)s, &match2, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001053 OF_ERROR_NONE);
1054 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1055 FREE(octets.data);
1056""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1057
1058 out.write("""
1059 return TEST_PASS;
1060}
1061""")
1062
1063 out.write("""
1064int run_match_tests(void)
1065{
1066 RUN_TEST(match_1);
1067 RUN_TEST(match_2);
1068 RUN_TEST(match_3);
1069 RUN_TEST(match_utils);
1070
1071 return TEST_PASS;
1072}
1073""")
1074
1075def gen_msg_test(out, name):
1076 loxi_utils.gen_c_copy_license(out)
1077 out.write("""
1078/**
1079 *
1080 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1081 *
1082 * Message-scalar tests for all versions
1083 */
1084
1085#include <locitest/test_common.h>
1086""")
1087 for version in of_g.of_version_range:
1088 for cls in of_g.ordered_messages:
1089 if not (cls, version) in of_g.base_length:
1090 continue
Rich Lane488b3c52013-06-21 18:11:02 -07001091 if type_maps.class_is_virtual(cls):
1092 continue
Rich Lanef70be942013-07-18 13:33:14 -07001093 bytes = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001094 out.write("""
1095static int
1096test_%(cls)s_create_%(v_name)s(void)
1097{
1098 %(cls)s_t *obj;
1099 uint8_t *msg_buf;
1100 int value;
1101 int len;
1102
1103 obj = %(cls)s_new(%(v_name)s);
1104 TEST_ASSERT(obj != NULL);
1105 TEST_ASSERT(obj->version == %(v_name)s);
1106 TEST_ASSERT(obj->length == %(bytes)d);
1107 TEST_ASSERT(obj->parent == NULL);
1108 TEST_ASSERT(obj->object_id == %(enum)s);
1109
1110 /* Set up incrementing values for scalar members */
1111 value = %(cls)s_%(v_name)s_populate_scalars(obj, 1);
1112 TEST_ASSERT(value != 0);
1113
1114 /* Grab the underlying buffer from the message */
1115 len = obj->length;
1116 of_object_wire_buffer_steal((of_object_t *)obj, &msg_buf);
1117 TEST_ASSERT(msg_buf != NULL);
1118 %(cls)s_delete(obj);
1119 /* TODO: */
1120 TEST_ASSERT(of_message_to_object_id(msg_buf, len) == %(enum)s);
1121 obj = %(cls)s_new_from_message(OF_BUFFER_TO_MESSAGE(msg_buf));
1122
1123 TEST_ASSERT(obj != NULL);
1124
1125 /* @fixme Set up all message objects (recursively?) */
1126
1127 value = %(cls)s_%(v_name)s_check_scalars(obj, 1);
1128 TEST_ASSERT(value != 0);
1129
1130 %(cls)s_delete(obj);
1131
1132 return TEST_PASS;
1133}
1134""" % dict(cls=cls, version=version, enum=loxi_utils.enum_name(cls),
1135 v_name=loxi_utils.version_to_name(version), bytes=bytes))
1136
1137 out.write("""
1138int
1139run_message_tests(void)
1140{
1141""")
1142 for version in of_g.of_version_range:
1143 for cls in of_g.ordered_messages:
1144 if not (cls, version) in of_g.base_length:
1145 continue
Rich Lane488b3c52013-06-21 18:11:02 -07001146 if type_maps.class_is_virtual(cls):
1147 continue
Rich Lanea06d0c32013-03-25 08:52:03 -07001148 test_name = "%s_create_%s" % (cls, loxi_utils.version_to_name(version))
1149 out.write(" RUN_TEST(%s);\n" % test_name)
1150
1151 out.write("\n return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -07001152
Rich Lanea06d0c32013-03-25 08:52:03 -07001153
1154def gen_list_setup_check(out, cls, version):
1155 """
1156 Generate functions that populate and check a list with two
1157 of each type of subclass it supports
1158 """
1159 out.write("""
1160/**
1161 * Populate a list of type %(cls)s with two of each type of subclass
1162 * @param list Pointer to the list to be populated
1163 * @param value The seed value to use in populating the list
1164 * @returns The value after increments for this object's values
1165 */
1166int
1167%(cls)s_%(v_name)s_populate(
1168 %(cls)s_t *list, int value)
1169{
1170""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1171 base_type = loxi_utils.list_to_entry_type(cls)
1172 out.write("""
1173 %(base_type)s_t elt;
1174 int cur_len = 0;
1175""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001176
Rich Lanea06d0c32013-03-25 08:52:03 -07001177 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -07001178 sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
Rich Lanea06d0c32013-03-25 08:52:03 -07001179 v_name = loxi_utils.version_to_name(version)
1180
1181 if len(sub_classes) == 0:
1182 out.write(" /* No subclasses for %s */\n"% base_type)
1183 out.write(" %s_t *elt_p;\n" % base_type)
1184 out.write("\n elt_p = &elt;\n")
1185 else:
1186 out.write(" /* Declare pointers for each subclass */\n")
1187 for instance, subcls in sub_classes:
1188 out.write(" %s_t *%s;\n" % (subcls, instance))
1189 out.write("\n /* Instantiate pointers for each subclass */\n")
1190 for instance, subcls in sub_classes:
1191 out.write(" %s = &elt.%s;\n" % (instance, instance))
1192
1193# if type_maps.class_is_virtual(base_type):
1194# out.write("""\
1195# TEST_OK(%(base_type)s_header_init(
1196# (%(base_type)s_header_t *)&elt, %(v_name)s, -1, 1));
1197# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1198# else:
1199# out.write("""\
1200# TEST_OK(%(base_type)s_init(&elt, %(v_name)s, -1, 1));
1201# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1202
1203 if len(sub_classes) == 0: # No inheritance case
1204 inst_len = loxi_utils.base_type_to_length(base_type, version)
1205 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
1206 else:
1207 for instance, subcls in sub_classes:
1208 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001209 setup_instance(out, cls, subcls, instance, v_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001210 inst_len, version)
1211 out.write("""
1212 return value;
1213}
1214""")
1215 out.write("""
1216/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001217 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -07001218 * %(cls)s_%(v_name)s_populate
1219 * @param list Pointer to the list that was populated
1220 * @param value Starting value for checking
1221 * @returns The value after increments for this object's values
1222 */
1223int
1224%(cls)s_%(v_name)s_check(
1225 %(cls)s_t *list, int value)
1226{
1227""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1228 base_type = loxi_utils.list_to_entry_type(cls)
1229 out.write("""
1230 %(base_type)s_t elt;
1231 int count = 0;
1232 int rv;
1233""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001234
Rich Lanea06d0c32013-03-25 08:52:03 -07001235
1236 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -07001237 sub_classes = [(instance, subcls) for (instance, subcls) in sub_classes if not type_maps.class_is_virtual(subcls)]
Rich Lanea06d0c32013-03-25 08:52:03 -07001238 v_name = loxi_utils.version_to_name(version)
1239
1240 if len(sub_classes) == 0:
1241 entry_count = 2
1242 out.write(" /* No subclasses for %s */\n"% base_type)
1243 out.write(" %s_t *elt_p;\n" % base_type)
1244 out.write("\n elt_p = &elt;\n")
1245 else:
1246 entry_count = 2 * len(sub_classes) # Two of each type appended
1247 out.write(" /* Declare pointers for each subclass */\n")
1248 for instance, subcls in sub_classes:
1249 out.write(" %s_t *%s;\n" % (subcls, instance))
1250 out.write("\n /* Instantiate pointers for each subclass */\n")
1251 for instance, subcls in sub_classes:
1252 out.write(" %s = &elt.%s;\n" % (instance, instance))
1253
1254 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
1255 if len(sub_classes) == 0: # No inheritance case
1256 if loxi_utils.class_is_var_len(base_type, version):
1257 inst_len = -1
1258 else:
1259 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -07001260 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001261 version, True)
1262 else:
1263 count = 0
1264 for instance, subcls in sub_classes:
1265 count += 1
1266 if loxi_utils.class_is_var_len(subcls, version):
1267 inst_len = -1
1268 else:
1269 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001270 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001271 version, count==len(sub_classes))
1272 out.write("""
1273""" % dict(base_type=base_type))
1274
1275 out.write("""
1276 /* Do an iterate to test the iterator */
1277 %(u_cls)s_ITER(list, &elt, rv) {
1278 count += 1;
1279 }
1280
1281 TEST_ASSERT(rv == OF_ERROR_RANGE);
1282 TEST_ASSERT(count == %(entry_count)d);
1283
1284 /* We shoehorn a test of the dup functions here */
1285 {
1286 %(cls)s_t *dup;
1287
1288 TEST_ASSERT((dup = %(cls)s_dup(list)) != NULL);
1289 TEST_ASSERT(dup->length == list->length);
1290 TEST_ASSERT(dup->object_id == list->object_id);
1291 TEST_ASSERT(dup->version == list->version);
1292 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1293 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1294 of_object_delete((of_object_t *)dup);
1295
1296 /* And now for the generic dup function */
1297 TEST_ASSERT((dup = (%(cls)s_t *)
1298 of_object_dup(list)) != NULL);
1299 TEST_ASSERT(dup->length == list->length);
1300 TEST_ASSERT(dup->object_id == list->object_id);
1301 TEST_ASSERT(dup->version == list->version);
1302 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1303 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1304 of_object_delete((of_object_t *)dup);
1305 }
1306
1307 return value;
1308}
1309""" % dict(cls=cls, u_cls=cls.upper(), entry_count=entry_count))
1310
1311
1312def gen_class_setup_check(out, cls, version):
1313 out.write("""
1314/**
1315 * Populate all members of an object of type %(cls)s
1316 * with incrementing values
1317 * @param obj Pointer to an object to populate
1318 * @param value The seed value to use in populating the object
1319 * @returns The value after increments for this object's values
1320 */
1321
1322int
1323%(cls)s_%(v_name)s_populate(
1324 %(cls)s_t *obj, int value)
1325{
1326""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1327 members, member_types = loxi_utils.all_member_types_get(cls, version)
1328 for m_type in member_types:
1329 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1330 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1331 else:
1332 out.write(" %s *%s;\n" % (m_type, var_name_map(m_type)))
1333 out.write("""
1334 /* Run thru accessors after new to ensure okay */
1335""")
1336 for member in members:
1337 m_type = member["m_type"]
1338 m_name = member["name"]
1339 if loxi_utils.skip_member_name(m_name):
1340 continue
1341 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1342 out.write("""\
1343 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1344""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1345 else:
1346 sub_cls = m_type[:-2] # Trim _t
1347 out.write("""\
1348 {
1349 %(sub_cls)s_t sub_cls;
1350
1351 /* Test bind */
1352 %(cls)s_%(m_name)s_bind(obj, &sub_cls);
1353 }
Andreas Wundsam53256162013-05-02 14:05:53 -07001354""" % dict(var_name=var_name_map(m_type), cls=cls,
Rich Lanea06d0c32013-03-25 08:52:03 -07001355 m_name=m_name, sub_cls=sub_cls,
1356 v_name=loxi_utils.version_to_name(version)))
1357
1358 out.write("""
1359 value = %(cls)s_%(v_name)s_populate_scalars(
1360 obj, value);
1361 TEST_ASSERT(value != 0);
1362""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1363
1364 for member in members:
1365 m_type = member["m_type"]
1366 m_name = member["name"]
1367 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1368 continue
1369 if loxi_utils.skip_member_name(m_name):
1370 continue
1371 if m_type == "of_match_t":
1372 out.write("""\
1373 value = of_match_populate(&%(var_name)s, %(v_name)s, value);
1374 TEST_ASSERT(value != 0);
1375 %(cls)s_%(m_name)s_set(
1376 obj, &%(var_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001377""" % dict(cls=cls, var_name=var_name_map(m_type),
Rich Lanea06d0c32013-03-25 08:52:03 -07001378 m_name=m_name, v_name=loxi_utils.version_to_name(version)))
1379 elif m_type == "of_octets_t":
1380 out.write("""\
1381 value = of_octets_populate(&%(var_name)s, value);
1382 TEST_ASSERT(value != 0);
1383 %(cls)s_%(m_name)s_set(
1384 obj, &%(var_name)s);
1385 if (octets.bytes) {
1386 FREE(octets.data);
1387 }
1388""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1389 else:
1390 sub_cls = m_type[:-2] # Trim _t
1391 out.write("""
1392 %(var_name)s = %(sub_cls)s_new(%(v_name)s);
1393 TEST_ASSERT(%(var_name)s != NULL);
1394 value = %(sub_cls)s_%(v_name)s_populate(
1395 %(var_name)s, value);
1396 TEST_ASSERT(value != 0);
1397 %(cls)s_%(m_name)s_set(
1398 obj, %(var_name)s);
1399 %(sub_cls)s_delete(%(var_name)s);
1400""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1401 var_name=var_name_map(m_type),
1402 v_name=loxi_utils.version_to_name(version)))
1403
1404 out.write("""
1405 return value;
1406}
1407""")
1408
1409 out.write("""
1410/**
1411 * Check all members of an object of type %(cls)s
1412 * populated by the above function
1413 * @param obj Pointer to an object to check
1414 * @param value Starting value for checking
1415 * @returns The value after increments for this object's values
1416 */
1417
1418int
1419%(cls)s_%(v_name)s_check(
1420 %(cls)s_t *obj, int value)
1421{
1422""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1423 members, member_types = loxi_utils.all_member_types_get(cls, version)
1424 for m_type in member_types:
1425 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1426 continue
1427 if loxi_utils.type_is_of_object(m_type):
1428 continue
1429 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1430 out.write("""
1431 value = %(cls)s_%(v_name)s_check_scalars(
1432 obj, value);
1433 TEST_ASSERT(value != 0);
1434""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1435
1436 for member in members:
1437 m_type = member["m_type"]
1438 m_name = member["name"]
1439 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1440 continue
1441 if loxi_utils.skip_member_name(m_name):
1442 continue
1443 if m_type == "of_match_t":
1444 out.write("""\
1445 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1446 value = of_match_check(&%(var_name)s, %(v_name)s, value);
1447""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1448 v_name=loxi_utils.version_to_name(version)))
1449 elif m_type == "of_octets_t":
1450 out.write("""\
1451 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1452 value = of_octets_check(&%(var_name)s, value);
1453""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1454 v_name=loxi_utils.version_to_name(version)))
1455 else:
1456 sub_cls = m_type[:-2] # Trim _t
1457 out.write("""
1458 { /* Use get/delete to access on check */
1459 %(m_type)s *%(m_name)s_ptr;
1460
1461 %(m_name)s_ptr = %(cls)s_%(m_name)s_get(obj);
1462 TEST_ASSERT(%(m_name)s_ptr != NULL);
1463 value = %(sub_cls)s_%(v_name)s_check(
1464 %(m_name)s_ptr, value);
1465 TEST_ASSERT(value != 0);
1466 %(sub_cls)s_delete(%(m_name)s_ptr);
1467 }
1468""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1469 var_name=var_name_map(m_type),
1470 v_name=loxi_utils.version_to_name(version)))
1471
1472 out.write("""
1473 /* We shoehorn a test of the dup functions here */
1474 {
1475 %(cls)s_t *dup;
1476
1477 TEST_ASSERT((dup = %(cls)s_dup(obj)) != NULL);
1478 TEST_ASSERT(dup->length == obj->length);
1479 TEST_ASSERT(dup->object_id == obj->object_id);
1480 TEST_ASSERT(dup->version == obj->version);
1481 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1482 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1483 of_object_delete((of_object_t *)dup);
1484
1485 /* And now for the generic dup function */
1486 TEST_ASSERT((dup = (%(cls)s_t *)
1487 of_object_dup(obj)) != NULL);
1488 TEST_ASSERT(dup->length == obj->length);
1489 TEST_ASSERT(dup->object_id == obj->object_id);
1490 TEST_ASSERT(dup->version == obj->version);
1491 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1492 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1493 of_object_delete((of_object_t *)dup);
1494 }
1495
1496 return value;
1497}
1498""" % dict(cls=cls))
1499
1500def unified_accessor_test_case(out, cls, version):
1501 """
1502 Generate one test case for the given version and class
1503 """
1504
1505 members, member_types = scalar_member_types_get(cls, version)
Rich Lanef70be942013-07-18 13:33:14 -07001506 length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001507 v_name = loxi_utils.version_to_name(version)
1508
1509 out.write("""
1510static int
1511test_%(cls)s_%(v_name)s(void)
1512{
1513 %(cls)s_t *obj;
1514 obj = %(cls)s_new(%(v_name)s);
1515 TEST_ASSERT(obj != NULL);
1516 TEST_ASSERT(obj->version == %(v_name)s);
1517 TEST_ASSERT(obj->length == %(length)d);
1518 TEST_ASSERT(obj->parent == NULL);
1519 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001520""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001521 v_name=v_name, length=length, version=version))
1522 if (not type_maps.class_is_virtual(cls)) or loxi_utils.class_is_list(cls):
1523 out.write("""
1524 if (obj->wire_length_get != NULL) {
1525 int length;
1526
1527 obj->wire_length_get((of_object_t *)obj, &length);
1528 TEST_ASSERT(length == %(length)d);
1529 }
1530 if (obj->wire_type_get != NULL) {
1531 of_object_id_t obj_id;
1532
1533 obj->wire_type_get((of_object_t *)obj, &obj_id);
1534 TEST_ASSERT(obj_id == %(u_cls)s);
1535 }
1536
1537 /* Set up incrementing values for members */
1538 TEST_ASSERT(%(cls)s_%(v_name)s_populate(
1539 obj, 1) != 0);
1540
1541 /* Check values just set */
1542 TEST_ASSERT(%(cls)s_%(v_name)s_check(
1543 obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001544""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001545 v_name=v_name, length=length, version=version))
1546
1547 out.write("""
1548 %(cls)s_delete(obj);
1549
1550 /* To do: Check memory */
1551 return TEST_PASS;
1552}
1553""" % dict(cls=cls))
1554
1555
1556def gen_unified_accessor_funs(out):
1557 for version in of_g.of_version_range:
1558 for cls in of_g.standard_class_order:
1559 if not loxi_utils.class_in_version(cls, version):
1560 continue
1561 if cls in type_maps.inheritance_map:
1562 continue
1563 elif loxi_utils.class_is_list(cls):
1564 gen_list_setup_check(out, cls, version)
1565 else:
1566 gen_class_setup_check(out, cls, version)
1567
1568def gen_unified_accessor_tests(out, name):
1569 loxi_utils.gen_c_copy_license(out)
1570 out.write("""
1571/**
1572 *
1573 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1574 *
1575 * Unified simple class instantiation tests for all versions
1576 */
1577
1578#include <locitest/test_common.h>
1579""")
1580 for version in of_g.of_version_range:
1581 for cls in of_g.standard_class_order:
1582 if not loxi_utils.class_in_version(cls, version):
1583 continue
1584 if cls in type_maps.inheritance_map:
1585 continue
1586 unified_accessor_test_case(out, cls, version)
1587
1588 out.write("""
1589int
1590run_unified_accessor_tests(void)
1591{
1592""")
1593 for version in of_g.of_version_range:
1594 v_name = loxi_utils.version_to_name(version)
1595 for cls in of_g.standard_class_order:
1596 if not loxi_utils.class_in_version(cls, version):
1597 continue
1598 if cls in type_maps.inheritance_map:
1599 continue
1600 test_name = "%s_%s" % (cls, v_name)
1601 out.write(" RUN_TEST(%s);\n" % test_name)
1602
1603 out.write(" return TEST_PASS;\n}\n");
1604
1605
1606
1607################################################################
1608#
1609# Object duplication functions
1610#
1611# These exercise the accessors to create duplicate objects.
1612# They are used in the LOCI test shim which sits in an OF
1613# protocol stream.
1614#
1615# TODO
1616# Resolve version stuff
1617# Complete list dup
1618
1619def gen_dup_list(out, cls, version):
1620 ver_name = loxi_utils.version_to_name(version)
1621 elt_type = loxi_utils.list_to_entry_type(cls)
1622 out.write("""
1623/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001624 * Duplicate a list of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001625 * using accessor functions
1626 * @param src Pointer to object to be duplicated
1627 * @returns A new object of type %(cls)s.
1628 *
1629 * The caller is responsible for deleting the returned value
1630 */
1631%(cls)s_t *
1632%(cls)s_%(ver_name)s_dup(
1633 %(cls)s_t *src)
1634{
1635 %(elt_type)s_t src_elt;
1636 %(elt_type)s_t *dst_elt;
1637 int rv;
1638 %(cls)s_t *dst;
1639
1640 if ((dst = %(cls)s_new(src->version)) == NULL) {
1641 return NULL;
1642 }
1643""" % dict(elt_type=elt_type, cls=cls, ver_name=ver_name))
1644
1645 out.write("""
1646 %(u_cls)s_ITER(src, &src_elt, rv) {
1647 if ((dst_elt = %(elt_type)s_%(ver_name)s_dup(&src_elt)) == NULL) {
1648 of_object_delete((of_object_t *)dst);
1649 return NULL;
1650 }
1651 _TRY_FREE(%(cls)s_append(dst, dst_elt),
1652 dst, NULL);
1653 of_object_delete((of_object_t *)dst_elt);
1654 }
1655
1656 return dst;
1657}
1658""" % dict(u_cls=cls.upper(), elt_type=elt_type, cls=cls, ver_name=ver_name))
1659
1660
1661def gen_dup_inheritance(out, cls, version):
1662 ver_name = loxi_utils.version_to_name(version)
1663 out.write("""
1664/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001665 * Duplicate a super class object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001666 * @param src Pointer to object to be duplicated
1667 * @returns A new object of type %(cls)s.
1668 *
1669 * The caller is responsible for deleting the returned value
1670 */
1671%(cls)s_t *
1672%(cls)s_%(ver_name)s_dup(
1673 %(cls)s_t *src)
1674{
1675""" % dict(cls=cls, ver_name=ver_name))
1676
1677 # For each subclass, check if this is an instance of that subclass
1678 version_classes = type_maps.inheritance_data[cls][version]
1679 for sub_cls in version_classes:
1680 sub_enum = (cls + "_" + sub_cls).upper()
1681 out.write("""
1682 if (src->header.object_id == %(sub_enum)s) {
1683 return (%(cls)s_t *)%(cls)s_%(sub_cls)s_%(ver_name)s_dup(
1684 &src->%(sub_cls)s);
1685 }
1686""" % dict(sub_cls=sub_cls, ver_name=ver_name, sub_enum=sub_enum, cls=cls))
1687
1688 out.write("""
1689 return NULL;
1690}
1691""")
1692
1693
1694def gen_dup_cls(out, cls, version):
1695 """
1696 Generate duplication routine for class cls
1697 """
1698 ver_name = loxi_utils.version_to_name(version)
1699
1700 out.write("""
1701/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001702 * Duplicate an object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001703 * using accessor functions
1704 * @param src Pointer to object to be duplicated
1705 * @returns A new object of type %(cls)s.
1706 *
1707 * The caller is responsible for deleting the returned value
1708 */
1709%(cls)s_t *
1710%(cls)s_%(ver_name)s_dup(
1711 %(cls)s_t *src)
1712{
1713 %(cls)s_t *dst;
1714""" % dict(cls=cls, ver_name=ver_name))
1715
1716 # Get members and types for the class
1717 members, member_types = loxi_utils.all_member_types_get(cls, version)
1718
1719 # Add declarations for each member type
1720 for m_type in member_types:
1721 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1722 # Declare instance of these
1723 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1724 else:
1725 out.write("""
1726 %(m_type)s src_%(v_name)s;
1727 %(m_type)s *dst_%(v_name)s;
1728""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
1729
1730 out.write("""
1731 if ((dst = %(cls)s_new(src->version)) == NULL) {
1732 return NULL;
1733 }
1734""" % dict(cls=cls))
1735
1736 for member in members:
1737 m_type = member["m_type"]
1738 m_name = member["name"]
1739 if loxi_utils.skip_member_name(m_name):
1740 continue
1741 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1742 out.write("""
1743 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1744 %(cls)s_%(m_name)s_set(dst, %(v_name)s);
1745""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1746 elif m_type in ["of_match_t", "of_octets_t"]:
1747 out.write("""
1748 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1749 %(cls)s_%(m_name)s_set(dst, &%(v_name)s);
1750""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1751 else:
1752 sub_cls = m_type[:-2] # Trim _t
1753 out.write("""
1754 %(cls)s_%(m_name)s_bind(
1755 src, &src_%(v_name)s);
1756 dst_%(v_name)s = %(sub_cls)s_%(ver_name)s_dup(&src_%(v_name)s);
1757 if (dst_%(v_name)s == NULL) {
1758 %(cls)s_delete(dst);
1759 return NULL;
1760 }
1761 %(cls)s_%(m_name)s_set(dst, dst_%(v_name)s);
1762 %(sub_cls)s_delete(dst_%(v_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001763""" % dict(sub_cls=sub_cls, cls=cls, m_name=m_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001764 v_name=var_name_map(m_type), ver_name=ver_name))
1765
1766 out.write("""
1767 return dst;
1768}
1769""")
1770
1771def gen_version_dup(out=sys.stdout):
1772 """
1773 Generate duplication routines for each object type
1774 """
1775 out.write("""
1776/* Special try macro for duplicating */
1777#define _TRY_FREE(op, obj, rv) do { \\
1778 int _rv; \\
1779 if ((_rv = (op)) < 0) { \\
1780 LOCI_LOG_ERROR("ERROR %d at %s:%d\\n", _rv, __FILE__, __LINE__); \\
1781 of_object_delete((of_object_t *)(obj)); \\
1782 return (rv); \\
1783 } \\
1784 } while (0)
1785""")
1786
1787 for version in of_g.of_version_range:
1788 for cls in of_g.standard_class_order:
1789 if not loxi_utils.class_in_version(cls, version):
1790 continue
1791 if cls in type_maps.inheritance_map:
1792 gen_dup_inheritance(out, cls, version)
1793 elif loxi_utils.class_is_list(cls):
1794 gen_dup_list(out, cls, version)
1795 else:
1796 gen_dup_cls(out, cls, version)
1797
1798def gen_dup(out=sys.stdout):
1799 """
1800 Generate non-version specific duplication routines for each object type
1801 """
1802
1803 for cls in of_g.standard_class_order:
1804 out.write("""
1805%(cls)s_t *
1806%(cls)s_dup(
1807 %(cls)s_t *src)
1808{
1809""" % dict(cls=cls))
1810 for version in of_g.of_version_range:
1811 if not loxi_utils.class_in_version(cls, version):
1812 continue
1813 hdr = "header." if cls in type_maps.inheritance_map else ""
1814
1815 ver_name = loxi_utils.version_to_name(version)
1816 out.write("""
1817 if (src->%(hdr)sversion == %(ver_name)s) {
1818 return %(cls)s_%(ver_name)s_dup(src);
1819 }
1820""" % dict(cls=cls, ver_name=ver_name, hdr=hdr))
1821
1822 out.write("""
1823 /* Class not supported in given version */
1824 return NULL;
1825}
1826""")
1827
1828def dup_c_gen(out, name):
1829 """
1830 Generate the C file for duplication functions
1831 """
1832 loxi_utils.gen_c_copy_license(out)
1833 out.write("""\
1834/*
1835 * Duplication functions for all OF objects
1836 *
1837 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1838 *
1839 * These are test functions for exercising accessors. You can call
1840 * of_object_dup for an efficient duplication.
1841 */
1842
1843#define DISABLE_WARN_UNUSED_RESULT
1844#include "loci_log.h"
1845#include <locitest/of_dup.h>
1846
1847""")
1848
1849 gen_version_dup(out)
1850 gen_dup(out)
1851
1852
1853def dup_h_gen(out, name):
1854 """
1855 Generate the header file for duplication functions
1856 """
1857
1858 loxi_utils.gen_c_copy_license(out)
1859 out.write("""
1860/*
1861 * Duplication function header file
1862 *
1863 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1864 */
1865
1866#if !defined(_OF_DUP_H_)
1867#define _OF_DUP_H_
1868
1869#include <loci/loci.h>
1870""")
1871
1872 for cls in of_g.standard_class_order:
1873 out.write("""
1874extern %(cls)s_t *
1875 %(cls)s_dup(
1876 %(cls)s_t *src);
1877""" % dict(cls=cls))
1878
1879 for version in of_g.of_version_range:
1880 for cls in of_g.standard_class_order:
1881 if not loxi_utils.class_in_version(cls, version):
1882 continue
1883 ver_name = loxi_utils.version_to_name(version)
1884 out.write("""
1885extern %(cls)s_t *
1886 %(cls)s_%(ver_name)s_dup(
1887 %(cls)s_t *src);
1888""" % dict(cls=cls, ver_name=ver_name))
1889
1890 out.write("\n#endif /* _OF_DUP_H_ */\n")
1891
1892def gen_log_test(out):
1893 """
1894 Generate test for obj log calls
1895
1896 Define a trivial handler for object logging; call all obj log fns
1897 """
1898 out.write("""
1899
1900/**
1901 * Test object dump functions
1902 */
1903
1904int
1905test_dump_objs(void)
1906{
1907 of_object_t *obj;
1908
1909 FILE *out = fopen("/dev/null", "w");
1910
1911 /* Call each obj dump function */
1912""")
1913 for version in of_g.of_version_range:
1914 for j, cls in enumerate(of_g.all_class_order):
1915 if not loxi_utils.class_in_version(cls, version):
1916 continue
1917 if cls in type_maps.inheritance_map:
1918 continue
1919 out.write("""
1920 obj = (of_object_t *)%(cls)s_new(%(version)s);
1921 of_object_dump((loci_writer_f)fprintf, out, obj);
1922 of_object_delete(obj);
1923""" % dict(cls=cls, version=of_g.of_version_wire2name[version]))
Andreas Wundsam53256162013-05-02 14:05:53 -07001924
Rich Lanea06d0c32013-03-25 08:52:03 -07001925 out.write("""
1926 fclose(out);
1927 return TEST_PASS;
1928}
1929""")
1930
1931def gen_ident_tests(out):
1932 """
1933 Generate tests for identifiers
1934
1935 For all idents, instantiate, test version supported macros
1936 For flags, set it, test it, clear it, test it.
1937 """
1938 out.write("""
1939/**
1940 * Test cases for all flag accessor macros
1941 * These only test self consistency (and that they compile)
1942 */
1943int
1944test_ident_macros(void)
1945{
1946 int value __attribute__((unused));
1947 uint32_t flags;
1948
1949""")
1950
1951 for ident, info in of_g.identifiers.items():
1952 if not identifiers.defined_versions_agree(of_g.identifiers,
1953 of_g.target_version_list,
1954 ident):
1955 # @fixme
1956 continue
1957 out.write(" value = %s;\n" % ident)
1958 for version in of_g.target_version_list:
1959 if version in info["values_by_version"].keys():
1960 out.write(" TEST_ASSERT(%s_SUPPORTED(%s));\n" %
1961 (ident, of_g.of_version_wire2name[version]))
1962 else:
1963 out.write(" TEST_ASSERT(!%s_SUPPORTED(%s));\n" %
1964 (ident, of_g.of_version_wire2name[version]))
1965 if flags.ident_is_flag(ident):
1966 # Grab first supported version
1967 for version in info["values_by_version"]:
1968 break
1969 out.write("""
1970 flags = 0;
1971 %(ident)s_SET(flags, %(ver_name)s);
1972 TEST_ASSERT(flags == %(ident)s_BY_VERSION(%(ver_name)s));
1973 TEST_ASSERT(%(ident)s_TEST(flags, %(ver_name)s));
1974 %(ident)s_CLEAR(flags, %(ver_name)s);
1975 TEST_ASSERT(flags == 0);
1976 TEST_ASSERT(!%(ident)s_TEST(flags, %(ver_name)s));
1977""" % dict(ident=ident, ver_name=of_g.of_version_wire2name[version]))
1978
1979 out.write("""
1980 return TEST_PASS;
1981}
1982""")
1983
Rich Laneccae0312013-07-21 23:34:13 -07001984def gen_datafiles_tests(out, name):
1985 tests = []
1986 for filename in test_data.list_files():
1987 data = test_data.read(filename)
1988 if not 'c' in data:
1989 continue
1990 name = filename[:-5].replace("/", "_")
1991 tests.append(dict(name=name,
1992 filename=filename,
1993 c=data['c'],
1994 binary=data['binary']))
1995
1996 util.render_template(out, "test_data.c", tests=tests)