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