blob: 14ab24e95b5331061b975031151c66d6362c8122 [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 }
264 return value;
265}
266
267int
268of_match_check(of_match_t *match, of_version_t version, int value)
269{
270 of_match_t check;
271
272 value = of_match_populate(&check, match->version, value);
273 TEST_ASSERT(value != 0);
274 TEST_ASSERT(MEMCMP(match, &check, sizeof(check)) == 0);
275
276 return value;
277}
278""")
279
280def gen_common_test_header(out, name):
281 loxi_utils.gen_c_copy_license(out)
282 out.write("""
283/*
284 * Test header file
285 *
286 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
287 */
288
289#if !defined(_TEST_COMMON_H_)
290#define _TEST_COMMON_H_
291
292#define DISABLE_WARN_UNUSED_RESULT
293#include <loci/loci.h>
294#include <locitest/of_dup.h>
295#include <locitest/unittest.h>
296
297extern int global_error;
298extern int exit_on_error;
299
300/* @todo Make option for -k to continue tests if errors */
301#define RUN_TEST(test) do { \\
302 int rv; \\
303 TESTCASE(test, rv); \\
304 if (rv != TEST_PASS) { \\
305 global_error=1; \\
306 if (exit_on_error) return(1); \\
307 } \\
308 } while(0)
309
310#define TEST_OK(op) TEST_ASSERT((op) == OF_ERROR_NONE)
311#define TEST_INDIGO_OK(op) TEST_ASSERT((op) == INDIGO_ERROR_NONE)
312
313/*
314 * Declarations of functions to populate scalar values in a a class
315 */
316
317extern void of_test_str_fill(uint8_t *buf, int value, int len);
318extern int of_test_str_check(uint8_t *buf, int value, int len);
319
320
321extern int of_octets_populate(of_octets_t *octets, int value);
322extern int of_octets_check(of_octets_t *octets, int value);
323extern int of_match_populate(of_match_t *match, of_version_t version,
324 int value);
325extern int of_match_check(of_match_t *match, of_version_t version, int value);
326extern int test_ident_macros(void);
327extern int test_dump_objs(void);
328
329/* In test_match_utils.c */
330extern int test_match_utils(void);
331
332extern int run_unified_accessor_tests(void);
333extern int run_match_tests(void);
334extern int run_utility_tests(void);
335
336extern int run_scalar_acc_tests(void);
337extern int run_list_tests(void);
338extern int run_message_tests(void);
339extern int run_setup_from_add_tests(void);
340
341extern int run_validator_tests(void);
342
343extern int run_list_limits_tests(void);
344
345extern int test_ext_objs(void);
Rich Laneccae0312013-07-21 23:34:13 -0700346extern int test_datafiles(void);
Rich Lanea06d0c32013-03-25 08:52:03 -0700347
348""")
349
350 for version in of_g.of_version_range:
351 for cls in of_g.standard_class_order:
352 if not loxi_utils.class_in_version(cls, version):
353 continue
354 if cls in type_maps.inheritance_map:
355 continue
356 out.write("""
357extern int %(cls)s_%(v_name)s_populate(
358 %(cls)s_t *obj, int value);
359extern int %(cls)s_%(v_name)s_check(
360 %(cls)s_t *obj, int value);
361extern int %(cls)s_%(v_name)s_populate_scalars(
362 %(cls)s_t *obj, int value);
363extern int %(cls)s_%(v_name)s_check_scalars(
364 %(cls)s_t *obj, int value);
365""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
366
367 out.write("""
368/*
369 * Declarations for list population and check primitives
370 */
371""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700372
Rich Lanea06d0c32013-03-25 08:52:03 -0700373 for version in of_g.of_version_range:
374 for cls in of_g.ordered_list_objects:
375 if cls in type_maps.inheritance_map:
376 continue
377
378 if version in of_g.unified[cls]:
379 out.write("""
380extern int
381 list_setup_%(cls)s_%(v_name)s(
382 %(cls)s_t *list, int value);
383extern int
384 list_check_%(cls)s_%(v_name)s(
385 %(cls)s_t *list, int value);
386""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
387
388 out.write("\n#endif /* _TEST_COMMON_H_ */\n")
389
390def gen_common_test(out, name):
391 """
392 Generate common test content including main
393 """
394 loxi_utils.gen_c_copy_license(out)
395 out.write("""
396/*
397 * Common test code for LOCI
398 *
399 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
400 */
401
402#define DISABLE_WARN_UNUSED_RESULT
403#include "loci_log.h"
404#include <loci/loci_obj_dump.h>
405#include <locitest/unittest.h>
406#include <locitest/test_common.h>
407
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900408/* mcheck is a glibc extension */
409#if defined(__linux__)
Rich Lanea06d0c32013-03-25 08:52:03 -0700410#include <mcheck.h>
411#define MCHECK_INIT mcheck(NULL)
YAMAMOTO Takashi071b5912013-07-02 08:37:39 +0900412#else
Rich Lanea06d0c32013-03-25 08:52:03 -0700413#define MCHECK_INIT do { } while (0)
414#endif
415
416/**
417 * Exit on error if set to 1
418 */
419int exit_on_error = 1;
420
421/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700422 * Global error state: 0 is okay, 1 is error
Rich Lanea06d0c32013-03-25 08:52:03 -0700423 */
424int global_error = 0;
425
426extern int run_unified_accessor_tests(void);
427extern int run_match_tests(void);
428extern int run_utility_tests(void);
429
430extern int run_scalar_acc_tests(void);
431extern int run_list_tests(void);
432extern int run_message_tests(void);
433
434/**
435 * Macros for initializing and checking scalar types
436 *
437 * @param var The variable being initialized or checked
438 * @param val The integer value to set/check against, see below
439 *
440 * Note that equality means something special for strings. Each byte
441 * is initialized to an incrementing value. So check is done against that.
442 *
443 */
444
445""")
446 for t in scalar_types:
447 if t in integer_types:
448 out.write("""
449#define VAR_%s_INIT(var, val) var = (%s)(val)
450#define VAR_%s_CHECK(var, val) ((var) == (%s)(val))
451""" % (t.upper(), t, t.upper(), t))
452 else:
453 out.write("""
454#define VAR_%s_INIT(var, val) \\
455 of_test_str_fill((uint8_t *)&(var), val, sizeof(var))
456#define VAR_%s_CHECK(var, val) \\
457 of_test_str_check((uint8_t *)&(var), val, sizeof(var))
458""" % (t.upper(), t.upper()))
459
460 gen_fill_string(out)
461 gen_scalar_set_check_funs(out)
462 gen_list_set_check_funs(out)
463 gen_unified_accessor_funs(out)
464
465 gen_ident_tests(out)
466 gen_log_test(out)
467
468def gen_message_scalar_test(out, name):
469 """
470 Generate test cases for message objects, scalar accessors
471 """
472
473 loxi_utils.gen_c_copy_license(out)
474 out.write("""
475/**
476 *
477 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
478 *
479 * Message-scalar tests for all versions
480 */
481
482#include <locitest/test_common.h>
483""")
484 for version in of_g.of_version_range:
485 v_name = loxi_utils.version_to_name(version)
486 out.write("""
487/**
488 * Message-scalar tests for version %s
489 */
490""" % v_name)
491 for cls in of_g.standard_class_order:
492 if cls in type_maps.inheritance_map:
493 continue
494 if version in of_g.unified[cls]:
495 message_scalar_test(out, version, cls)
496
497 out.write("""
498int
499run_scalar_acc_tests(void)
500{
501""")
502 for version in of_g.of_version_range:
503 v_name = loxi_utils.version_to_name(version)
504 for cls in of_g.standard_class_order:
505 if cls in type_maps.inheritance_map:
506 continue
507 if version in of_g.unified[cls]:
508 test_name = "%s_%s" % (cls, v_name)
509 out.write(" RUN_TEST(%s_scalar);\n" % test_name)
510
511 out.write(" return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -0700512
Rich Lanea06d0c32013-03-25 08:52:03 -0700513def message_scalar_test(out, version, cls):
514 """
515 Generate one test case for the given version and class
516 """
517
518 members, member_types = scalar_member_types_get(cls, version)
Rich Lanef70be942013-07-18 13:33:14 -0700519 length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -0700520 v_name = loxi_utils.version_to_name(version)
521
522 out.write("""
523static int
524test_%(cls)s_%(v_name)s_scalar(void)
525{
526 %(cls)s_t *obj;
527
528 obj = %(cls)s_new(%(v_name)s);
529 TEST_ASSERT(obj != NULL);
530 TEST_ASSERT(obj->version == %(v_name)s);
531 TEST_ASSERT(obj->length == %(length)d);
532 TEST_ASSERT(obj->parent == NULL);
533 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -0700534""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700535 v_name=v_name, length=length, version=version))
536 if not type_maps.class_is_virtual(cls):
537 out.write("""
538 if (obj->wire_length_get != NULL) {
539 int length;
540
541 obj->wire_length_get((of_object_t *)obj, &length);
542 TEST_ASSERT(length == %(length)d);
543 }
544
545 /* Set up incrementing values for scalar members */
546 %(cls)s_%(v_name)s_populate_scalars(obj, 1);
547
548 /* Check values just set */
549 TEST_ASSERT(%(cls)s_%(v_name)s_check_scalars(obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700550""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700551 v_name=v_name, length=length, version=version))
552
553 out.write("""
554 %(cls)s_delete(obj);
555
556 /* To do: Check memory */
557 return TEST_PASS;
558}
559""" % dict(cls=cls))
560
561# Get the members and list of scalar types for members of a given class
562def scalar_member_types_get(cls, version):
563 member_types = []
564
565 if not version in of_g.unified[cls]:
566 return ([], [])
567
568 if "use_version" in of_g.unified[cls][version]:
569 v = of_g.unified[cls][version]["use_version"]
570 members = of_g.unified[cls][v]["members"]
571 else:
572 members = of_g.unified[cls][version]["members"]
573 # Accumulate variables that are supported
574 for member in members:
575 m_type = member["m_type"]
576 m_name = member["name"]
Andreas Wundsam53256162013-05-02 14:05:53 -0700577 if (not loxi_utils.type_is_scalar(m_type) or
Rich Lanea06d0c32013-03-25 08:52:03 -0700578 ignore_member(cls, version, m_name, m_type)):
579 continue
580 if not m_type in member_types:
581 member_types.append(m_type)
582
583 return (members, member_types)
584
585def scalar_funs_instance(out, cls, version, members, member_types):
586 """
587 Generate one instance of scalar set/check functions
588 """
589 out.write("""
590/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700591 * Populate the scalar values in obj of type %(cls)s,
592 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700593 * @param obj Pointer to an object to populate
594 * @param value The seed value to use in populating the object
595 * @returns The value after increments for this object's values
596 */
597int %(cls)s_%(v_name)s_populate_scalars(
598 %(cls)s_t *obj, int value) {
599""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
600 # Declare string types
601 for t in member_types:
602 out.write(" %s %s;\n" % (t, var_name_map(t)))
603 for member in members:
604 m_type = member["m_type"]
605 m_name = member["name"]
606 if (not loxi_utils.type_is_scalar(m_type) or
607 ignore_member(cls, version, m_name, m_type)):
608 continue
609 v_name = var_name_map(m_type);
610 out.write("""
611 VAR_%(u_type)s_INIT(%(v_name)s, value);
612 %(cls)s_%(m_name)s_set(obj, %(v_name)s);
613 value += 1;
614""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
615 out.write("""
616 return value;
617}
618""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700619
Rich Lanea06d0c32013-03-25 08:52:03 -0700620 out.write("""
621/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700622 * Check scalar values in obj of type %(cls)s,
623 * version %(v_name)s
Rich Lanea06d0c32013-03-25 08:52:03 -0700624 * @param obj Pointer to an object to check
625 * @param value Starting value for checking
626 * @returns The value after increments for this object's values
627 */
628int %(cls)s_%(v_name)s_check_scalars(
629 %(cls)s_t *obj, int value) {
630""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
631
632 for t in member_types:
633 out.write(" %s %s;\n" % (t, var_name_map(t)))
634 for member in members:
635 m_type = member["m_type"]
636 m_name = member["name"]
637 if (not loxi_utils.type_is_scalar(m_type) or
638 ignore_member(cls, version, m_name, m_type)):
639 continue
640 v_name = var_name_map(m_type);
641 out.write("""
642 %(cls)s_%(m_name)s_get(obj, &%(v_name)s);
643 TEST_ASSERT(VAR_%(u_type)s_CHECK(%(v_name)s, value));
644 value += 1;
645""" % dict(cls=cls, m_name=m_name, u_type=m_type.upper(), v_name=v_name))
646
647 out.write("""
648 return value;
649}
650
651""")
652
653def gen_scalar_set_check_funs(out):
654 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700655 For each object class with scalar members, generate functions that
Rich Lanea06d0c32013-03-25 08:52:03 -0700656 set and check their values
657 """
658 for version in of_g.of_version_range:
659 for cls in of_g.standard_class_order:
660 (members, member_types) = scalar_member_types_get(cls, version)
661 scalar_funs_instance(out, cls, version, members, member_types)
662
663
664# Helper function to set up a subclass instance for a test
665def setup_instance(out, cls, subcls, instance, v_name, inst_len, version):
666 base_type = loxi_utils.list_to_entry_type(cls)
667 setup_template = """
668 %(subcls)s_init(%(inst)s, %(v_name)s, -1, 1);
Andreas Wundsam53256162013-05-02 14:05:53 -0700669 %(cls)s_append_bind(list,
Rich Lanea06d0c32013-03-25 08:52:03 -0700670 (%(base_type)s_t *)%(inst)s);
671 value = %(subcls)s_%(v_name)s_populate(
672 %(inst)s, value);
673 cur_len += %(inst)s->length;
674 TEST_ASSERT(list->length == cur_len);
675"""
676 out.write("""
677 /* Append two instances of type %s */
678""" % subcls)
679 for i in range(2):
680 out.write(setup_template %
Andreas Wundsam53256162013-05-02 14:05:53 -0700681 dict(inst=instance, subcls=subcls, v_name=v_name,
682 base_type=base_type, cls=cls, inst_len=inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700683 version=version))
684
685def check_instance(out, cls, subcls, instance, v_name, inst_len, version, last):
686 check_template = ""
687 if inst_len >= 0:
688 check_template = """
689 TEST_ASSERT(%(inst)s->length == %(inst_len)d);
690 if (%(inst)s->wire_length_get != NULL) {
691 int length;
692
693 %(inst)s->wire_length_get(
694 (of_object_t *)&elt, &length);
695 TEST_ASSERT(length == %(inst_len)d);
696 }
697"""
698 check_template += """
699 TEST_ASSERT(%(inst)s->object_id == %(elt_name)s);
700 value = %(subcls)s_%(v_name)s_check(
701 %(inst)s, value);
702 TEST_ASSERT(value != 0);
703"""
704 out.write("\n /* Check two instances of type %s */" % instance)
705
Andreas Wundsam53256162013-05-02 14:05:53 -0700706 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700707 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
708 inst=instance, subcls=subcls,
709 v_name=loxi_utils.version_to_name(version)))
710 out.write("""\
711 TEST_OK(%(cls)s_next(list, &elt));
712""" % dict(cls=cls))
713
Andreas Wundsam53256162013-05-02 14:05:53 -0700714 out.write(check_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700715 dict(elt_name=loxi_utils.enum_name(subcls), inst_len=inst_len,
716 inst=instance, subcls=subcls,
717 v_name=loxi_utils.version_to_name(version)))
718 if last:
719 out.write("""\
720 TEST_ASSERT(%(cls)s_next(list, &elt) == OF_ERROR_RANGE);
721""" % dict(cls=cls))
722 else:
723 out.write("""\
724 TEST_OK(%(cls)s_next(list, &elt));
725""" % dict(cls=cls))
726
727def setup_list_fn(out, version, cls):
728 """
729 Generate a helper function that populates a list with two
730 of each type of subclass it supports
731 """
732 out.write("""
733/**
734 * Set up a list of type %(cls)s with two of each type of subclass
735 */
736int
737list_setup_%(cls)s_%(v_name)s(
738 %(cls)s_t *list, int value)
739{
740""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
741 base_type = loxi_utils.list_to_entry_type(cls)
742 out.write("""
743 %(base_type)s_t elt;
744 int cur_len = 0;
745""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700746
Rich Lanea06d0c32013-03-25 08:52:03 -0700747 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -0700748 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 -0700749 v_name = loxi_utils.version_to_name(version)
750
751 if len(sub_classes) == 0:
752 out.write(" /* No subclasses for %s */\n"% base_type)
753 out.write(" %s_t *elt_p;\n" % base_type)
754 out.write("\n elt_p = &elt;\n")
755 else:
756 out.write(" /* Declare pointers for each subclass */\n")
757 for instance, subcls in sub_classes:
758 out.write(" %s_t *%s;\n" % (subcls, instance))
759 out.write("\n /* Instantiate pointers for each subclass */\n")
760 for instance, subcls in sub_classes:
761 out.write(" %s = &elt.%s;\n" % (instance, instance))
762
763 if len(sub_classes) == 0: # No inheritance case
764 inst_len = loxi_utils.base_type_to_length(base_type, version)
765 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
766 else:
767 for instance, subcls in sub_classes:
768 inst_len = of_g.base_length[(subcls, version)]
769 setup_instance(out, cls, subcls, instance, v_name, inst_len, version)
770 out.write("""
771
772 return value;
773}
774""")
775
776def check_list_fn(out, version, cls):
777 """
778 Generate a helper function that checks a list populated by above fn
779 """
780 out.write("""
781/**
Andreas Wundsam53256162013-05-02 14:05:53 -0700782 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -0700783 * list_setup_%(cls)s_%(v_name)s
784 */
785int
786list_check_%(cls)s_%(v_name)s(
787 %(cls)s_t *list, int value)
788{
789""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
790 base_type = loxi_utils.list_to_entry_type(cls)
791 out.write("""
792 %(base_type)s_t elt;
793""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -0700794
Rich Lanea06d0c32013-03-25 08:52:03 -0700795 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -0700796 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 -0700797 v_name = loxi_utils.version_to_name(version)
798
799 if len(sub_classes) == 0:
800 out.write(" /* No subclasses for %s */\n"% base_type)
801 out.write(" %s_t *elt_p;\n" % base_type)
802 out.write("\n elt_p = &elt;\n")
803 else:
804 out.write(" /* Declare pointers for each subclass */\n")
805 for instance, subcls in sub_classes:
806 out.write(" %s_t *%s;\n" % (subcls, instance))
807 out.write("\n /* Instantiate pointers for each subclass */\n")
808 for instance, subcls in sub_classes:
809 out.write(" %s = &elt.%s;\n" % (instance, instance))
810
811 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
812 if len(sub_classes) == 0: # No inheritance case
813 if loxi_utils.class_is_var_len(base_type, version):
814 inst_len = -1
815 else:
816 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -0700817 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700818 version, True)
819 else:
820 count = 0
821 for instance, subcls in sub_classes:
822 count += 1
823 if loxi_utils.class_is_var_len(subcls, version):
824 inst_len = -1
825 else:
826 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -0700827 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -0700828 version, count==len(sub_classes))
829
830 out.write("""
831 return value;
832}
833""" % dict(base_type=base_type))
834
835def gen_list_set_check_funs(out):
836 for version in of_g.of_version_range:
837 for cls in of_g.ordered_list_objects:
838 if cls in type_maps.inheritance_map:
839 continue
840
841 if version in of_g.unified[cls]:
842 setup_list_fn(out, version, cls)
843 check_list_fn(out, version, cls)
844
845# Maybe: Get a map from list class to parent, mem_name of container
846
847def list_test(out, version, cls):
848 out.write("""
849static int
850test_%(cls)s_%(v_name)s(void)
851{
852""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
853 base_type = loxi_utils.list_to_entry_type(cls)
854
855 out.write(""" %(cls)s_t *list;
856 int value = 1;
857""" % dict(cls=cls, base_type=base_type))
858
859 out.write("""
860 list = %(cls)s_new(%(v_name)s);
861 TEST_ASSERT(list != NULL);
862 TEST_ASSERT(list->version == %(v_name)s);
863 TEST_ASSERT(list->length == 0);
864 TEST_ASSERT(list->parent == NULL);
865 TEST_ASSERT(list->object_id == %(enum_cls)s);
866
867 value = list_setup_%(cls)s_%(v_name)s(list, value);
868 TEST_ASSERT(value != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -0700869""" % dict(cls=cls, base_type=base_type, v_name=loxi_utils.version_to_name(version),
Rich Lanea06d0c32013-03-25 08:52:03 -0700870 enum_cls=loxi_utils.enum_name(cls)))
871
872 out.write("""
873 /* Now check values */
874 value = 1;
875 value = list_check_%(cls)s_%(v_name)s(list, value);
876 TEST_ASSERT(value != 0);
877""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
878
879 out.write("""
880 %(cls)s_delete(list);
881
882 return TEST_PASS;
883}
884""" % dict(cls=cls))
885
886def gen_list_test(out, name):
887 """
888 Generate base line test cases for lists
889 @param out The file handle to write to
890 """
891
892 loxi_utils.gen_c_copy_license(out)
893 out.write("""
894/**
895 *
896 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
897 *
898 * Message-scalar tests for all versions
899 */
900
901#include <locitest/test_common.h>
902""")
Andreas Wundsam53256162013-05-02 14:05:53 -0700903
Rich Lanea06d0c32013-03-25 08:52:03 -0700904 for version in of_g.of_version_range:
905 v_name = loxi_utils.version_to_name(version)
906 out.write("""
907/**
908 * Baseline list tests for version %s
909 */
910""" % v_name)
911 for cls in of_g.ordered_list_objects:
912 if cls in type_maps.inheritance_map:
913 continue
914 if version in of_g.unified[cls]:
915 list_test(out, version, cls)
916
917 out.write("""
918int
919run_list_tests(void)
920{
921""")
922 for version in of_g.of_version_range:
923 v_name = loxi_utils.version_to_name(version)
924 for cls in of_g.ordered_list_objects:
925 if cls in type_maps.inheritance_map:
926 continue
927 if version in of_g.unified[cls]:
928 test_name = "%s_%s" % (cls, v_name)
929 out.write(" RUN_TEST(%s);\n" % test_name)
930
931 out.write("\n return TEST_PASS;\n}\n");
932
933def gen_match_test(out, name):
934 """
935 Generate baseline tests for match functions
936 """
937
938 loxi_utils.gen_c_copy_license(out)
939 out.write("""\
940/**
941 *
942 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
943 *
944 * Message-scalar tests for all versions
945 * @fixme These are mostly hard coded now.
946 */
947
948#include <locitest/test_common.h>
949
950static int
951test_match_1(void)
952{
953 of_match_v1_t *m_v1;
954 of_match_v2_t *m_v2;
955 of_match_v3_t *m_v3;
956 of_match_v4_t *m_v4;
957 of_match_t match;
958 int value = 1;
959 int idx;
960 uint32_t exp_value;
961
962 /* Verify default values for ip mask map */
963 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
964 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
965 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
966 if (idx < 32) {
967 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
968 }
969 }
970
971 TEST_ASSERT(of_ip_mask_map_set(17, 0xabcdef00) == OF_ERROR_NONE);
972 TEST_ASSERT(of_ip_mask_to_index(0xabcdef00) == 17);
973 TEST_ASSERT(of_ip_index_to_mask(17) == 0xabcdef00);
974
975 TEST_ASSERT(of_ip_mask_map_set(62, 0xabcdefff) == OF_ERROR_NONE);
976 TEST_ASSERT(of_ip_mask_to_index(0xabcdefff) == 62);
977 TEST_ASSERT(of_ip_index_to_mask(62) == 0xabcdefff);
978
979 /* Test re-init */
980 of_ip_mask_map_init();
981 for (idx = 0; idx < OF_IP_MASK_MAP_COUNT; idx++) {
982 exp_value = (idx < 32) ? ~((1 << idx) - 1) : 0;
983 TEST_ASSERT(of_ip_index_to_mask(idx) == exp_value);
984 if (idx < 32) {
985 TEST_ASSERT(of_ip_mask_to_index(exp_value) == idx);
986 }
987 }
988""")
989
990 for version in of_g.of_version_range:
991 out.write("""
992 /* Create/populate/convert and delete for version %(v_name)s */
993 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
994 TEST_ASSERT(m_v%(version)d != NULL);
995 TEST_ASSERT((value = of_match_populate(&match, %(v_name)s, value)) > 0);
996 TEST_OK(of_match_to_wire_match_v%(version)d(&match, m_v%(version)d));
997 of_match_v%(version)d_delete(m_v%(version)d);
998""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
999
1000 out.write("""
1001 return TEST_PASS;
1002}
1003""")
1004
1005 out.write("""
1006static int
1007test_match_2(void)
1008{
1009 of_match_v1_t *m_v1;
1010 of_match_v2_t *m_v2;
1011 of_match_v3_t *m_v3;
1012 of_match_v3_t *m_v4;
1013 of_match_t match1;
1014 of_match_t match2;
1015 int value = 1;
1016""")
1017
1018 for version in of_g.of_version_range:
1019 out.write("""
1020 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
1021 m_v%(version)d = of_match_v%(version)d_new(%(v_name)s);
1022 TEST_ASSERT(m_v%(version)d != NULL);
1023 TEST_OK(of_match_to_wire_match_v%(version)d(&match1, m_v%(version)d));
1024 TEST_OK(of_match_v%(version)d_to_match(m_v%(version)d, &match2));
1025 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1026 of_match_v%(version)d_delete(m_v%(version)d);
1027""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1028
1029 out.write("""
1030 return TEST_PASS;
1031}
1032""")
1033
1034 out.write("""
1035static int
1036test_match_3(void)
1037{
1038 of_match_t match1;
1039 of_match_t match2;
1040 int value = 1;
1041 of_octets_t octets;
1042""")
1043 for version in of_g.of_version_range:
1044 out.write("""
1045 /* Serialize to version %(v_name)s */
1046 TEST_ASSERT((value = of_match_populate(&match1, %(v_name)s, value)) > 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001047 TEST_ASSERT(of_match_serialize(%(v_name)s, &match1, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001048 OF_ERROR_NONE);
Andreas Wundsam53256162013-05-02 14:05:53 -07001049 TEST_ASSERT(of_match_deserialize(%(v_name)s, &match2, &octets) ==
Rich Lanea06d0c32013-03-25 08:52:03 -07001050 OF_ERROR_NONE);
1051 TEST_ASSERT(memcmp(&match1, &match2, sizeof(match1)) == 0);
1052 FREE(octets.data);
1053""" % dict(v_name=loxi_utils.version_to_name(version), version=version))
1054
1055 out.write("""
1056 return TEST_PASS;
1057}
1058""")
1059
1060 out.write("""
1061int run_match_tests(void)
1062{
1063 RUN_TEST(match_1);
1064 RUN_TEST(match_2);
1065 RUN_TEST(match_3);
1066 RUN_TEST(match_utils);
1067
1068 return TEST_PASS;
1069}
1070""")
1071
1072def gen_msg_test(out, name):
1073 loxi_utils.gen_c_copy_license(out)
1074 out.write("""
1075/**
1076 *
1077 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1078 *
1079 * Message-scalar tests for all versions
1080 */
1081
1082#include <locitest/test_common.h>
1083""")
1084 for version in of_g.of_version_range:
1085 for cls in of_g.ordered_messages:
1086 if not (cls, version) in of_g.base_length:
1087 continue
Rich Lane488b3c52013-06-21 18:11:02 -07001088 if type_maps.class_is_virtual(cls):
1089 continue
Rich Lanef70be942013-07-18 13:33:14 -07001090 bytes = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001091 out.write("""
1092static int
1093test_%(cls)s_create_%(v_name)s(void)
1094{
1095 %(cls)s_t *obj;
1096 uint8_t *msg_buf;
1097 int value;
1098 int len;
1099
1100 obj = %(cls)s_new(%(v_name)s);
1101 TEST_ASSERT(obj != NULL);
1102 TEST_ASSERT(obj->version == %(v_name)s);
1103 TEST_ASSERT(obj->length == %(bytes)d);
1104 TEST_ASSERT(obj->parent == NULL);
1105 TEST_ASSERT(obj->object_id == %(enum)s);
1106
1107 /* Set up incrementing values for scalar members */
1108 value = %(cls)s_%(v_name)s_populate_scalars(obj, 1);
1109 TEST_ASSERT(value != 0);
1110
1111 /* Grab the underlying buffer from the message */
1112 len = obj->length;
1113 of_object_wire_buffer_steal((of_object_t *)obj, &msg_buf);
1114 TEST_ASSERT(msg_buf != NULL);
1115 %(cls)s_delete(obj);
1116 /* TODO: */
1117 TEST_ASSERT(of_message_to_object_id(msg_buf, len) == %(enum)s);
1118 obj = %(cls)s_new_from_message(OF_BUFFER_TO_MESSAGE(msg_buf));
1119
1120 TEST_ASSERT(obj != NULL);
1121
1122 /* @fixme Set up all message objects (recursively?) */
1123
1124 value = %(cls)s_%(v_name)s_check_scalars(obj, 1);
1125 TEST_ASSERT(value != 0);
1126
1127 %(cls)s_delete(obj);
1128
1129 return TEST_PASS;
1130}
1131""" % dict(cls=cls, version=version, enum=loxi_utils.enum_name(cls),
1132 v_name=loxi_utils.version_to_name(version), bytes=bytes))
1133
1134 out.write("""
1135int
1136run_message_tests(void)
1137{
1138""")
1139 for version in of_g.of_version_range:
1140 for cls in of_g.ordered_messages:
1141 if not (cls, version) in of_g.base_length:
1142 continue
Rich Lane488b3c52013-06-21 18:11:02 -07001143 if type_maps.class_is_virtual(cls):
1144 continue
Rich Lanea06d0c32013-03-25 08:52:03 -07001145 test_name = "%s_create_%s" % (cls, loxi_utils.version_to_name(version))
1146 out.write(" RUN_TEST(%s);\n" % test_name)
1147
1148 out.write("\n return TEST_PASS;\n}\n");
Andreas Wundsam53256162013-05-02 14:05:53 -07001149
Rich Lanea06d0c32013-03-25 08:52:03 -07001150
1151def gen_list_setup_check(out, cls, version):
1152 """
1153 Generate functions that populate and check a list with two
1154 of each type of subclass it supports
1155 """
1156 out.write("""
1157/**
1158 * Populate a list of type %(cls)s with two of each type of subclass
1159 * @param list Pointer to the list to be populated
1160 * @param value The seed value to use in populating the list
1161 * @returns The value after increments for this object's values
1162 */
1163int
1164%(cls)s_%(v_name)s_populate(
1165 %(cls)s_t *list, int value)
1166{
1167""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1168 base_type = loxi_utils.list_to_entry_type(cls)
1169 out.write("""
1170 %(base_type)s_t elt;
1171 int cur_len = 0;
1172""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001173
Rich Lanea06d0c32013-03-25 08:52:03 -07001174 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -07001175 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 -07001176 v_name = loxi_utils.version_to_name(version)
1177
1178 if len(sub_classes) == 0:
1179 out.write(" /* No subclasses for %s */\n"% base_type)
1180 out.write(" %s_t *elt_p;\n" % base_type)
1181 out.write("\n elt_p = &elt;\n")
1182 else:
1183 out.write(" /* Declare pointers for each subclass */\n")
1184 for instance, subcls in sub_classes:
1185 out.write(" %s_t *%s;\n" % (subcls, instance))
1186 out.write("\n /* Instantiate pointers for each subclass */\n")
1187 for instance, subcls in sub_classes:
1188 out.write(" %s = &elt.%s;\n" % (instance, instance))
1189
1190# if type_maps.class_is_virtual(base_type):
1191# out.write("""\
1192# TEST_OK(%(base_type)s_header_init(
1193# (%(base_type)s_header_t *)&elt, %(v_name)s, -1, 1));
1194# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1195# else:
1196# out.write("""\
1197# TEST_OK(%(base_type)s_init(&elt, %(v_name)s, -1, 1));
1198# """ % dict(base_type=base_type, v_name=loxi_utils.version_to_name(version)))
1199
1200 if len(sub_classes) == 0: # No inheritance case
1201 inst_len = loxi_utils.base_type_to_length(base_type, version)
1202 setup_instance(out, cls, base_type, "elt_p", v_name, inst_len, version)
1203 else:
1204 for instance, subcls in sub_classes:
1205 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001206 setup_instance(out, cls, subcls, instance, v_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001207 inst_len, version)
1208 out.write("""
1209 return value;
1210}
1211""")
1212 out.write("""
1213/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001214 * Check a list of type %(cls)s generated by
Rich Lanea06d0c32013-03-25 08:52:03 -07001215 * %(cls)s_%(v_name)s_populate
1216 * @param list Pointer to the list that was populated
1217 * @param value Starting value for checking
1218 * @returns The value after increments for this object's values
1219 */
1220int
1221%(cls)s_%(v_name)s_check(
1222 %(cls)s_t *list, int value)
1223{
1224""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1225 base_type = loxi_utils.list_to_entry_type(cls)
1226 out.write("""
1227 %(base_type)s_t elt;
1228 int count = 0;
1229 int rv;
1230""" % dict(cls=cls, base_type=base_type))
Andreas Wundsam53256162013-05-02 14:05:53 -07001231
Rich Lanea06d0c32013-03-25 08:52:03 -07001232
1233 sub_classes = type_maps.sub_class_map(base_type, version)
Rich Lane1bd2bae2013-07-09 10:06:07 -07001234 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 -07001235 v_name = loxi_utils.version_to_name(version)
1236
1237 if len(sub_classes) == 0:
1238 entry_count = 2
1239 out.write(" /* No subclasses for %s */\n"% base_type)
1240 out.write(" %s_t *elt_p;\n" % base_type)
1241 out.write("\n elt_p = &elt;\n")
1242 else:
1243 entry_count = 2 * len(sub_classes) # Two of each type appended
1244 out.write(" /* Declare pointers for each subclass */\n")
1245 for instance, subcls in sub_classes:
1246 out.write(" %s_t *%s;\n" % (subcls, instance))
1247 out.write("\n /* Instantiate pointers for each subclass */\n")
1248 for instance, subcls in sub_classes:
1249 out.write(" %s = &elt.%s;\n" % (instance, instance))
1250
1251 out.write(" TEST_OK(%(cls)s_first(list, &elt));\n" % dict(cls=cls))
1252 if len(sub_classes) == 0: # No inheritance case
1253 if loxi_utils.class_is_var_len(base_type, version):
1254 inst_len = -1
1255 else:
1256 inst_len = loxi_utils.base_type_to_length(base_type, version)
Andreas Wundsam53256162013-05-02 14:05:53 -07001257 check_instance(out, cls, base_type, "elt_p", v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001258 version, True)
1259 else:
1260 count = 0
1261 for instance, subcls in sub_classes:
1262 count += 1
1263 if loxi_utils.class_is_var_len(subcls, version):
1264 inst_len = -1
1265 else:
1266 inst_len = of_g.base_length[(subcls, version)]
Andreas Wundsam53256162013-05-02 14:05:53 -07001267 check_instance(out, cls, subcls, instance, v_name, inst_len,
Rich Lanea06d0c32013-03-25 08:52:03 -07001268 version, count==len(sub_classes))
1269 out.write("""
1270""" % dict(base_type=base_type))
1271
1272 out.write("""
1273 /* Do an iterate to test the iterator */
1274 %(u_cls)s_ITER(list, &elt, rv) {
1275 count += 1;
1276 }
1277
1278 TEST_ASSERT(rv == OF_ERROR_RANGE);
1279 TEST_ASSERT(count == %(entry_count)d);
1280
1281 /* We shoehorn a test of the dup functions here */
1282 {
1283 %(cls)s_t *dup;
1284
1285 TEST_ASSERT((dup = %(cls)s_dup(list)) != NULL);
1286 TEST_ASSERT(dup->length == list->length);
1287 TEST_ASSERT(dup->object_id == list->object_id);
1288 TEST_ASSERT(dup->version == list->version);
1289 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1290 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1291 of_object_delete((of_object_t *)dup);
1292
1293 /* And now for the generic dup function */
1294 TEST_ASSERT((dup = (%(cls)s_t *)
1295 of_object_dup(list)) != NULL);
1296 TEST_ASSERT(dup->length == list->length);
1297 TEST_ASSERT(dup->object_id == list->object_id);
1298 TEST_ASSERT(dup->version == list->version);
1299 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1300 OF_OBJECT_BUFFER_INDEX(list, 0), list->length) == 0);
1301 of_object_delete((of_object_t *)dup);
1302 }
1303
1304 return value;
1305}
1306""" % dict(cls=cls, u_cls=cls.upper(), entry_count=entry_count))
1307
1308
1309def gen_class_setup_check(out, cls, version):
1310 out.write("""
1311/**
1312 * Populate all members of an object of type %(cls)s
1313 * with incrementing values
1314 * @param obj Pointer to an object to populate
1315 * @param value The seed value to use in populating the object
1316 * @returns The value after increments for this object's values
1317 */
1318
1319int
1320%(cls)s_%(v_name)s_populate(
1321 %(cls)s_t *obj, int value)
1322{
1323""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1324 members, member_types = loxi_utils.all_member_types_get(cls, version)
1325 for m_type in member_types:
1326 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1327 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1328 else:
1329 out.write(" %s *%s;\n" % (m_type, var_name_map(m_type)))
1330 out.write("""
1331 /* Run thru accessors after new to ensure okay */
1332""")
1333 for member in members:
1334 m_type = member["m_type"]
1335 m_name = member["name"]
1336 if loxi_utils.skip_member_name(m_name):
1337 continue
1338 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1339 out.write("""\
1340 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1341""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1342 else:
1343 sub_cls = m_type[:-2] # Trim _t
1344 out.write("""\
1345 {
1346 %(sub_cls)s_t sub_cls;
1347
1348 /* Test bind */
1349 %(cls)s_%(m_name)s_bind(obj, &sub_cls);
1350 }
Andreas Wundsam53256162013-05-02 14:05:53 -07001351""" % dict(var_name=var_name_map(m_type), cls=cls,
Rich Lanea06d0c32013-03-25 08:52:03 -07001352 m_name=m_name, sub_cls=sub_cls,
1353 v_name=loxi_utils.version_to_name(version)))
1354
1355 out.write("""
1356 value = %(cls)s_%(v_name)s_populate_scalars(
1357 obj, value);
1358 TEST_ASSERT(value != 0);
1359""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1360
1361 for member in members:
1362 m_type = member["m_type"]
1363 m_name = member["name"]
1364 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1365 continue
1366 if loxi_utils.skip_member_name(m_name):
1367 continue
1368 if m_type == "of_match_t":
1369 out.write("""\
1370 value = of_match_populate(&%(var_name)s, %(v_name)s, value);
1371 TEST_ASSERT(value != 0);
1372 %(cls)s_%(m_name)s_set(
1373 obj, &%(var_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001374""" % dict(cls=cls, var_name=var_name_map(m_type),
Rich Lanea06d0c32013-03-25 08:52:03 -07001375 m_name=m_name, v_name=loxi_utils.version_to_name(version)))
1376 elif m_type == "of_octets_t":
1377 out.write("""\
1378 value = of_octets_populate(&%(var_name)s, value);
1379 TEST_ASSERT(value != 0);
1380 %(cls)s_%(m_name)s_set(
1381 obj, &%(var_name)s);
1382 if (octets.bytes) {
1383 FREE(octets.data);
1384 }
1385""" % dict(var_name=var_name_map(m_type), cls=cls, m_name=m_name))
1386 else:
1387 sub_cls = m_type[:-2] # Trim _t
1388 out.write("""
1389 %(var_name)s = %(sub_cls)s_new(%(v_name)s);
1390 TEST_ASSERT(%(var_name)s != NULL);
1391 value = %(sub_cls)s_%(v_name)s_populate(
1392 %(var_name)s, value);
1393 TEST_ASSERT(value != 0);
1394 %(cls)s_%(m_name)s_set(
1395 obj, %(var_name)s);
1396 %(sub_cls)s_delete(%(var_name)s);
1397""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1398 var_name=var_name_map(m_type),
1399 v_name=loxi_utils.version_to_name(version)))
1400
1401 out.write("""
1402 return value;
1403}
1404""")
1405
1406 out.write("""
1407/**
1408 * Check all members of an object of type %(cls)s
1409 * populated by the above function
1410 * @param obj Pointer to an object to check
1411 * @param value Starting value for checking
1412 * @returns The value after increments for this object's values
1413 */
1414
1415int
1416%(cls)s_%(v_name)s_check(
1417 %(cls)s_t *obj, int value)
1418{
1419""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1420 members, member_types = loxi_utils.all_member_types_get(cls, version)
1421 for m_type in member_types:
1422 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1423 continue
1424 if loxi_utils.type_is_of_object(m_type):
1425 continue
1426 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1427 out.write("""
1428 value = %(cls)s_%(v_name)s_check_scalars(
1429 obj, value);
1430 TEST_ASSERT(value != 0);
1431""" % dict(cls=cls, v_name=loxi_utils.version_to_name(version)))
1432
1433 for member in members:
1434 m_type = member["m_type"]
1435 m_name = member["name"]
1436 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1437 continue
1438 if loxi_utils.skip_member_name(m_name):
1439 continue
1440 if m_type == "of_match_t":
1441 out.write("""\
1442 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1443 value = of_match_check(&%(var_name)s, %(v_name)s, value);
1444""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1445 v_name=loxi_utils.version_to_name(version)))
1446 elif m_type == "of_octets_t":
1447 out.write("""\
1448 %(cls)s_%(m_name)s_get(obj, &%(var_name)s);
1449 value = of_octets_check(&%(var_name)s, value);
1450""" % dict(cls=cls, var_name=var_name_map(m_type), m_name=m_name,
1451 v_name=loxi_utils.version_to_name(version)))
1452 else:
1453 sub_cls = m_type[:-2] # Trim _t
1454 out.write("""
1455 { /* Use get/delete to access on check */
1456 %(m_type)s *%(m_name)s_ptr;
1457
1458 %(m_name)s_ptr = %(cls)s_%(m_name)s_get(obj);
1459 TEST_ASSERT(%(m_name)s_ptr != NULL);
1460 value = %(sub_cls)s_%(v_name)s_check(
1461 %(m_name)s_ptr, value);
1462 TEST_ASSERT(value != 0);
1463 %(sub_cls)s_delete(%(m_name)s_ptr);
1464 }
1465""" % dict(cls=cls, sub_cls=sub_cls, m_name=m_name, m_type=m_type,
1466 var_name=var_name_map(m_type),
1467 v_name=loxi_utils.version_to_name(version)))
1468
1469 out.write("""
1470 /* We shoehorn a test of the dup functions here */
1471 {
1472 %(cls)s_t *dup;
1473
1474 TEST_ASSERT((dup = %(cls)s_dup(obj)) != NULL);
1475 TEST_ASSERT(dup->length == obj->length);
1476 TEST_ASSERT(dup->object_id == obj->object_id);
1477 TEST_ASSERT(dup->version == obj->version);
1478 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1479 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1480 of_object_delete((of_object_t *)dup);
1481
1482 /* And now for the generic dup function */
1483 TEST_ASSERT((dup = (%(cls)s_t *)
1484 of_object_dup(obj)) != NULL);
1485 TEST_ASSERT(dup->length == obj->length);
1486 TEST_ASSERT(dup->object_id == obj->object_id);
1487 TEST_ASSERT(dup->version == obj->version);
1488 TEST_ASSERT(MEMCMP(OF_OBJECT_BUFFER_INDEX(dup, 0),
1489 OF_OBJECT_BUFFER_INDEX(obj, 0), obj->length) == 0);
1490 of_object_delete((of_object_t *)dup);
1491 }
1492
1493 return value;
1494}
1495""" % dict(cls=cls))
1496
1497def unified_accessor_test_case(out, cls, version):
1498 """
1499 Generate one test case for the given version and class
1500 """
1501
1502 members, member_types = scalar_member_types_get(cls, version)
Rich Lanef70be942013-07-18 13:33:14 -07001503 length = of_g.base_length[(cls, version)] + of_g.extra_length.get((cls, version), 0)
Rich Lanea06d0c32013-03-25 08:52:03 -07001504 v_name = loxi_utils.version_to_name(version)
1505
1506 out.write("""
1507static int
1508test_%(cls)s_%(v_name)s(void)
1509{
1510 %(cls)s_t *obj;
1511 obj = %(cls)s_new(%(v_name)s);
1512 TEST_ASSERT(obj != NULL);
1513 TEST_ASSERT(obj->version == %(v_name)s);
1514 TEST_ASSERT(obj->length == %(length)d);
1515 TEST_ASSERT(obj->parent == NULL);
1516 TEST_ASSERT(obj->object_id == %(u_cls)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001517""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001518 v_name=v_name, length=length, version=version))
1519 if (not type_maps.class_is_virtual(cls)) or loxi_utils.class_is_list(cls):
1520 out.write("""
1521 if (obj->wire_length_get != NULL) {
1522 int length;
1523
1524 obj->wire_length_get((of_object_t *)obj, &length);
1525 TEST_ASSERT(length == %(length)d);
1526 }
1527 if (obj->wire_type_get != NULL) {
1528 of_object_id_t obj_id;
1529
1530 obj->wire_type_get((of_object_t *)obj, &obj_id);
1531 TEST_ASSERT(obj_id == %(u_cls)s);
1532 }
1533
1534 /* Set up incrementing values for members */
1535 TEST_ASSERT(%(cls)s_%(v_name)s_populate(
1536 obj, 1) != 0);
1537
1538 /* Check values just set */
1539 TEST_ASSERT(%(cls)s_%(v_name)s_check(
1540 obj, 1) != 0);
Andreas Wundsam53256162013-05-02 14:05:53 -07001541""" % dict(cls=cls, u_cls=cls.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -07001542 v_name=v_name, length=length, version=version))
1543
1544 out.write("""
1545 %(cls)s_delete(obj);
1546
1547 /* To do: Check memory */
1548 return TEST_PASS;
1549}
1550""" % dict(cls=cls))
1551
1552
1553def gen_unified_accessor_funs(out):
1554 for version in of_g.of_version_range:
1555 for cls in of_g.standard_class_order:
1556 if not loxi_utils.class_in_version(cls, version):
1557 continue
1558 if cls in type_maps.inheritance_map:
1559 continue
1560 elif loxi_utils.class_is_list(cls):
1561 gen_list_setup_check(out, cls, version)
1562 else:
1563 gen_class_setup_check(out, cls, version)
1564
1565def gen_unified_accessor_tests(out, name):
1566 loxi_utils.gen_c_copy_license(out)
1567 out.write("""
1568/**
1569 *
1570 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1571 *
1572 * Unified simple class instantiation tests for all versions
1573 */
1574
1575#include <locitest/test_common.h>
1576""")
1577 for version in of_g.of_version_range:
1578 for cls in of_g.standard_class_order:
1579 if not loxi_utils.class_in_version(cls, version):
1580 continue
1581 if cls in type_maps.inheritance_map:
1582 continue
1583 unified_accessor_test_case(out, cls, version)
1584
1585 out.write("""
1586int
1587run_unified_accessor_tests(void)
1588{
1589""")
1590 for version in of_g.of_version_range:
1591 v_name = loxi_utils.version_to_name(version)
1592 for cls in of_g.standard_class_order:
1593 if not loxi_utils.class_in_version(cls, version):
1594 continue
1595 if cls in type_maps.inheritance_map:
1596 continue
1597 test_name = "%s_%s" % (cls, v_name)
1598 out.write(" RUN_TEST(%s);\n" % test_name)
1599
1600 out.write(" return TEST_PASS;\n}\n");
1601
1602
1603
1604################################################################
1605#
1606# Object duplication functions
1607#
1608# These exercise the accessors to create duplicate objects.
1609# They are used in the LOCI test shim which sits in an OF
1610# protocol stream.
1611#
1612# TODO
1613# Resolve version stuff
1614# Complete list dup
1615
1616def gen_dup_list(out, cls, version):
1617 ver_name = loxi_utils.version_to_name(version)
1618 elt_type = loxi_utils.list_to_entry_type(cls)
1619 out.write("""
1620/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001621 * Duplicate a list of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001622 * using accessor functions
1623 * @param src Pointer to object to be duplicated
1624 * @returns A new object of type %(cls)s.
1625 *
1626 * The caller is responsible for deleting the returned value
1627 */
1628%(cls)s_t *
1629%(cls)s_%(ver_name)s_dup(
1630 %(cls)s_t *src)
1631{
1632 %(elt_type)s_t src_elt;
1633 %(elt_type)s_t *dst_elt;
1634 int rv;
1635 %(cls)s_t *dst;
1636
1637 if ((dst = %(cls)s_new(src->version)) == NULL) {
1638 return NULL;
1639 }
1640""" % dict(elt_type=elt_type, cls=cls, ver_name=ver_name))
1641
1642 out.write("""
1643 %(u_cls)s_ITER(src, &src_elt, rv) {
1644 if ((dst_elt = %(elt_type)s_%(ver_name)s_dup(&src_elt)) == NULL) {
1645 of_object_delete((of_object_t *)dst);
1646 return NULL;
1647 }
1648 _TRY_FREE(%(cls)s_append(dst, dst_elt),
1649 dst, NULL);
1650 of_object_delete((of_object_t *)dst_elt);
1651 }
1652
1653 return dst;
1654}
1655""" % dict(u_cls=cls.upper(), elt_type=elt_type, cls=cls, ver_name=ver_name))
1656
1657
1658def gen_dup_inheritance(out, cls, version):
1659 ver_name = loxi_utils.version_to_name(version)
1660 out.write("""
1661/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001662 * Duplicate a super class object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001663 * @param src Pointer to object to be duplicated
1664 * @returns A new object of type %(cls)s.
1665 *
1666 * The caller is responsible for deleting the returned value
1667 */
1668%(cls)s_t *
1669%(cls)s_%(ver_name)s_dup(
1670 %(cls)s_t *src)
1671{
1672""" % dict(cls=cls, ver_name=ver_name))
1673
1674 # For each subclass, check if this is an instance of that subclass
1675 version_classes = type_maps.inheritance_data[cls][version]
1676 for sub_cls in version_classes:
1677 sub_enum = (cls + "_" + sub_cls).upper()
1678 out.write("""
1679 if (src->header.object_id == %(sub_enum)s) {
1680 return (%(cls)s_t *)%(cls)s_%(sub_cls)s_%(ver_name)s_dup(
1681 &src->%(sub_cls)s);
1682 }
1683""" % dict(sub_cls=sub_cls, ver_name=ver_name, sub_enum=sub_enum, cls=cls))
1684
1685 out.write("""
1686 return NULL;
1687}
1688""")
1689
1690
1691def gen_dup_cls(out, cls, version):
1692 """
1693 Generate duplication routine for class cls
1694 """
1695 ver_name = loxi_utils.version_to_name(version)
1696
1697 out.write("""
1698/**
Andreas Wundsam53256162013-05-02 14:05:53 -07001699 * Duplicate an object of type %(cls)s
Rich Lanea06d0c32013-03-25 08:52:03 -07001700 * using accessor functions
1701 * @param src Pointer to object to be duplicated
1702 * @returns A new object of type %(cls)s.
1703 *
1704 * The caller is responsible for deleting the returned value
1705 */
1706%(cls)s_t *
1707%(cls)s_%(ver_name)s_dup(
1708 %(cls)s_t *src)
1709{
1710 %(cls)s_t *dst;
1711""" % dict(cls=cls, ver_name=ver_name))
1712
1713 # Get members and types for the class
1714 members, member_types = loxi_utils.all_member_types_get(cls, version)
1715
1716 # Add declarations for each member type
1717 for m_type in member_types:
1718 if loxi_utils.type_is_scalar(m_type) or m_type in ["of_match_t", "of_octets_t"]:
1719 # Declare instance of these
1720 out.write(" %s %s;\n" % (m_type, var_name_map(m_type)))
1721 else:
1722 out.write("""
1723 %(m_type)s src_%(v_name)s;
1724 %(m_type)s *dst_%(v_name)s;
1725""" % dict(m_type=m_type, v_name=var_name_map(m_type)))
1726
1727 out.write("""
1728 if ((dst = %(cls)s_new(src->version)) == NULL) {
1729 return NULL;
1730 }
1731""" % dict(cls=cls))
1732
1733 for member in members:
1734 m_type = member["m_type"]
1735 m_name = member["name"]
1736 if loxi_utils.skip_member_name(m_name):
1737 continue
1738 if loxi_utils.type_is_scalar(m_type): # Handled by call to scalar setup
1739 out.write("""
1740 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1741 %(cls)s_%(m_name)s_set(dst, %(v_name)s);
1742""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1743 elif m_type in ["of_match_t", "of_octets_t"]:
1744 out.write("""
1745 %(cls)s_%(m_name)s_get(src, &%(v_name)s);
1746 %(cls)s_%(m_name)s_set(dst, &%(v_name)s);
1747""" % dict(cls=cls, m_name=m_name, v_name=var_name_map(m_type)))
1748 else:
1749 sub_cls = m_type[:-2] # Trim _t
1750 out.write("""
1751 %(cls)s_%(m_name)s_bind(
1752 src, &src_%(v_name)s);
1753 dst_%(v_name)s = %(sub_cls)s_%(ver_name)s_dup(&src_%(v_name)s);
1754 if (dst_%(v_name)s == NULL) {
1755 %(cls)s_delete(dst);
1756 return NULL;
1757 }
1758 %(cls)s_%(m_name)s_set(dst, dst_%(v_name)s);
1759 %(sub_cls)s_delete(dst_%(v_name)s);
Andreas Wundsam53256162013-05-02 14:05:53 -07001760""" % dict(sub_cls=sub_cls, cls=cls, m_name=m_name,
Rich Lanea06d0c32013-03-25 08:52:03 -07001761 v_name=var_name_map(m_type), ver_name=ver_name))
1762
1763 out.write("""
1764 return dst;
1765}
1766""")
1767
1768def gen_version_dup(out=sys.stdout):
1769 """
1770 Generate duplication routines for each object type
1771 """
1772 out.write("""
1773/* Special try macro for duplicating */
1774#define _TRY_FREE(op, obj, rv) do { \\
1775 int _rv; \\
1776 if ((_rv = (op)) < 0) { \\
1777 LOCI_LOG_ERROR("ERROR %d at %s:%d\\n", _rv, __FILE__, __LINE__); \\
1778 of_object_delete((of_object_t *)(obj)); \\
1779 return (rv); \\
1780 } \\
1781 } while (0)
1782""")
1783
1784 for version in of_g.of_version_range:
1785 for cls in of_g.standard_class_order:
1786 if not loxi_utils.class_in_version(cls, version):
1787 continue
1788 if cls in type_maps.inheritance_map:
1789 gen_dup_inheritance(out, cls, version)
1790 elif loxi_utils.class_is_list(cls):
1791 gen_dup_list(out, cls, version)
1792 else:
1793 gen_dup_cls(out, cls, version)
1794
1795def gen_dup(out=sys.stdout):
1796 """
1797 Generate non-version specific duplication routines for each object type
1798 """
1799
1800 for cls in of_g.standard_class_order:
1801 out.write("""
1802%(cls)s_t *
1803%(cls)s_dup(
1804 %(cls)s_t *src)
1805{
1806""" % dict(cls=cls))
1807 for version in of_g.of_version_range:
1808 if not loxi_utils.class_in_version(cls, version):
1809 continue
1810 hdr = "header." if cls in type_maps.inheritance_map else ""
1811
1812 ver_name = loxi_utils.version_to_name(version)
1813 out.write("""
1814 if (src->%(hdr)sversion == %(ver_name)s) {
1815 return %(cls)s_%(ver_name)s_dup(src);
1816 }
1817""" % dict(cls=cls, ver_name=ver_name, hdr=hdr))
1818
1819 out.write("""
1820 /* Class not supported in given version */
1821 return NULL;
1822}
1823""")
1824
1825def dup_c_gen(out, name):
1826 """
1827 Generate the C file for duplication functions
1828 """
1829 loxi_utils.gen_c_copy_license(out)
1830 out.write("""\
1831/*
1832 * Duplication functions for all OF objects
1833 *
1834 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1835 *
1836 * These are test functions for exercising accessors. You can call
1837 * of_object_dup for an efficient duplication.
1838 */
1839
1840#define DISABLE_WARN_UNUSED_RESULT
1841#include "loci_log.h"
1842#include <locitest/of_dup.h>
1843
1844""")
1845
1846 gen_version_dup(out)
1847 gen_dup(out)
1848
1849
1850def dup_h_gen(out, name):
1851 """
1852 Generate the header file for duplication functions
1853 """
1854
1855 loxi_utils.gen_c_copy_license(out)
1856 out.write("""
1857/*
1858 * Duplication function header file
1859 *
1860 * AUTOMATICALLY GENERATED FILE. Edits will be lost on regen.
1861 */
1862
1863#if !defined(_OF_DUP_H_)
1864#define _OF_DUP_H_
1865
1866#include <loci/loci.h>
1867""")
1868
1869 for cls in of_g.standard_class_order:
1870 out.write("""
1871extern %(cls)s_t *
1872 %(cls)s_dup(
1873 %(cls)s_t *src);
1874""" % dict(cls=cls))
1875
1876 for version in of_g.of_version_range:
1877 for cls in of_g.standard_class_order:
1878 if not loxi_utils.class_in_version(cls, version):
1879 continue
1880 ver_name = loxi_utils.version_to_name(version)
1881 out.write("""
1882extern %(cls)s_t *
1883 %(cls)s_%(ver_name)s_dup(
1884 %(cls)s_t *src);
1885""" % dict(cls=cls, ver_name=ver_name))
1886
1887 out.write("\n#endif /* _OF_DUP_H_ */\n")
1888
1889def gen_log_test(out):
1890 """
1891 Generate test for obj log calls
1892
1893 Define a trivial handler for object logging; call all obj log fns
1894 """
1895 out.write("""
1896
1897/**
1898 * Test object dump functions
1899 */
1900
1901int
1902test_dump_objs(void)
1903{
1904 of_object_t *obj;
1905
1906 FILE *out = fopen("/dev/null", "w");
1907
1908 /* Call each obj dump function */
1909""")
1910 for version in of_g.of_version_range:
1911 for j, cls in enumerate(of_g.all_class_order):
1912 if not loxi_utils.class_in_version(cls, version):
1913 continue
1914 if cls in type_maps.inheritance_map:
1915 continue
1916 out.write("""
1917 obj = (of_object_t *)%(cls)s_new(%(version)s);
1918 of_object_dump((loci_writer_f)fprintf, out, obj);
1919 of_object_delete(obj);
1920""" % dict(cls=cls, version=of_g.of_version_wire2name[version]))
Andreas Wundsam53256162013-05-02 14:05:53 -07001921
Rich Lanea06d0c32013-03-25 08:52:03 -07001922 out.write("""
1923 fclose(out);
1924 return TEST_PASS;
1925}
1926""")
1927
1928def gen_ident_tests(out):
1929 """
1930 Generate tests for identifiers
1931
1932 For all idents, instantiate, test version supported macros
1933 For flags, set it, test it, clear it, test it.
1934 """
1935 out.write("""
1936/**
1937 * Test cases for all flag accessor macros
1938 * These only test self consistency (and that they compile)
1939 */
1940int
1941test_ident_macros(void)
1942{
1943 int value __attribute__((unused));
1944 uint32_t flags;
1945
1946""")
1947
1948 for ident, info in of_g.identifiers.items():
1949 if not identifiers.defined_versions_agree(of_g.identifiers,
1950 of_g.target_version_list,
1951 ident):
1952 # @fixme
1953 continue
1954 out.write(" value = %s;\n" % ident)
1955 for version in of_g.target_version_list:
1956 if version in info["values_by_version"].keys():
1957 out.write(" TEST_ASSERT(%s_SUPPORTED(%s));\n" %
1958 (ident, of_g.of_version_wire2name[version]))
1959 else:
1960 out.write(" TEST_ASSERT(!%s_SUPPORTED(%s));\n" %
1961 (ident, of_g.of_version_wire2name[version]))
1962 if flags.ident_is_flag(ident):
1963 # Grab first supported version
1964 for version in info["values_by_version"]:
1965 break
1966 out.write("""
1967 flags = 0;
1968 %(ident)s_SET(flags, %(ver_name)s);
1969 TEST_ASSERT(flags == %(ident)s_BY_VERSION(%(ver_name)s));
1970 TEST_ASSERT(%(ident)s_TEST(flags, %(ver_name)s));
1971 %(ident)s_CLEAR(flags, %(ver_name)s);
1972 TEST_ASSERT(flags == 0);
1973 TEST_ASSERT(!%(ident)s_TEST(flags, %(ver_name)s));
1974""" % dict(ident=ident, ver_name=of_g.of_version_wire2name[version]))
1975
1976 out.write("""
1977 return TEST_PASS;
1978}
1979""")
1980
Rich Laneccae0312013-07-21 23:34:13 -07001981def gen_datafiles_tests(out, name):
1982 tests = []
1983 for filename in test_data.list_files():
1984 data = test_data.read(filename)
1985 if not 'c' in data:
1986 continue
1987 name = filename[:-5].replace("/", "_")
1988 tests.append(dict(name=name,
1989 filename=filename,
1990 c=data['c'],
1991 binary=data['binary']))
1992
1993 util.render_template(out, "test_data.c", tests=tests)