Skip to content

Commit

Permalink
vRouter test framework
Browse files Browse the repository at this point in the history
Skeleton code to parse an xml specification file. Also, a sandesh
generator that parses the vRouter sandesh file and generates code
that parses the xml file and fills up the appropriate structure.

Change-Id: Ie7b0f9fd3faacd7e3906160b3fb52572673df274
Partial-BUG: #1455004
  • Loading branch information
anandhk-juniper committed May 15, 2015
1 parent 0ee4e19 commit d74aa41
Show file tree
Hide file tree
Showing 10 changed files with 1,590 additions and 1 deletion.
2 changes: 1 addition & 1 deletion utils/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ env.Append(CCFLAGS = '-g')
if 'install' in COMMAND_LINE_TARGETS:
VRutilsEnv.Append(SRC_INSTALL_TARGET = '/utils/')

subdirs = ['dkms']
subdirs = ['dkms', 'vtest']
for sdir in subdirs:
env.SConscript(sdir + '/SConscript',
exports='VRutilsEnv',
Expand Down
225 changes: 225 additions & 0 deletions utils/vtest/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
The xml file specification
-------------------------

<?xml version="1.0"?>
<test>
<test_name>Interface test</test_name>
<message>
<vif>
<m_op>Add</m_op>
<vif_type>Virtual</vif_type>
<vif_index>4</vif_index>
<vif_vrf>0</vif_vrf>
<vif_mac>00:01:02:03:04:05</vif_mac>
<vif_mtu>1514</vif_mtu>
</vif>
<message_return>0</message_return>
</message>

<test_result>
<message>
<vif>
<m_op>Get</m_op>
<vif_index>4</vif_index>
</vif>
</message>
<message_return>0</message_return>
<message_expect>
<vif>
<vif_type>Virtual</vif_type>
<vif_index>4</vif_index>
<vif_vrf>0</vif_vrf>
<vif_mac>00:01:02:03:04:05</vif_mac>
<vif_mtu>1514</vif_mtu>
</vif>
</message_expect>
</test_result>

</test>

The generated code from sandesh file processing
-----------------------------------------------

There is a sandesh compiler that parses the sandesh file and autogenerates
code to read values from specification file and assign it to corresponding
variables of the sandesh structure. It takes care of all known data types
of sandesh message (including list<type> and string). As of now, the compiler
generates 'vt_gen_sandesh.c' (that contains the above described functionality)
, 'vt_gen_message_modules.c' (that contains the list of nodes under the message
module of vtest), 'vt_gen_message_modules.h' (a header file that contains all
the required declarations) and 'vt_gen_expect.c' that sanitizes the received
message with expected values from the specification file.

The generator is still evolving. More functionality will be added to generator
on need basis.


Snap of code generated in 'vt_gen_sandesh.c'
-------------------------------------------

....

void *
vr_nexthop_req_node(xmlNodePtr node, struct vtest *test)
{
unsigned int list_size;
vr_nexthop_req *req;

req = calloc(sizeof(*req), 1);
if (!req)
return NULL;

node = node->xmlChildrenNode;
while (node) {
if (!node->content || !strlen(node->content)) {
return NULL;
}

if (!strncmp(node->name, "h_op", strlen(node->content))) {
req->h_op = vt_gen_op(node->content);
} else if (!strncmp(node->name, "nhr_type", strlen(node->content))) {
req->nhr_type = strtoul(node->content, NULL, 0);
} else if (!strncmp(node->name, "nhr_family", strlen(node->content))) {

....

} else if (!strncmp(node->name, "nhr_label_list", strlen(node->content))) {
req->nhr_label_list = vt_gen_list(node->content, GEN_TYPE_U32, &list_size);
req->nhr_label_list_size = list_size;
}
node = node->next;
}

return (void *)req;
}

Snap of code generated in 'vt_gen_message_modules.c'
----------------------------------------------------

/*
* Auto generated file
*/
#include <string.h>

#include <stdbool.h>

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

#include <vr_types.h>
#include <vt_gen_lib.h>
#include <vtest.h>

#include <vt_gen_message_modules.h>

struct vt_message_module vt_message_modules[] = {
{
.vmm_name = "vr_nexthop_req",
.vmm_node = vr_nexthop_req_node,
.vmm_expect = vr_nexthop_req_expect,
.vmm_size = sizeof(vr_nexthop_req),
},
{
.vmm_name = "vr_interface_req",
.vmm_node = vr_interface_req_node,

....
....

{
.vmm_name = "expect",
.vmm_node = vt_expect_node,
.vmm_size = 0,
},
};

unsigned int vt_message_modules_num =
sizeof(vt_message_modules) / sizeof(vt_message_modules[0]);


Snap of code generated in 'vt_gen_message_modules.h'
---------------------------------------------------

/*
* Auto generated file
*/
#ifndef __VT_GEN_MESSAGE_MODULES_H__
#define __VT_GEN_MESSAGE_MODULES_H__

#include <string.h>

#include <stdbool.h>

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

#include <vr_types.h>
#include <vt_gen_lib.h>
#include <vtest.h>

struct vt_message_module {
char *vmm_name;
void *(*vmm_node)(xmlNodePtr, struct vtest *);
bool (*vmm_expect)(xmlNodePtr, struct vtest *, void *);
unsigned int vmm_size;
};

extern void *vr_nexthop_req_node(xmlNodePtr, struct vtest *);
extern bool vr_nexthop_req_expect(xmlNodePtr, struct vtest *, void *);

....
....

extern void *vt_return_node(xmlNodePtr, struct vtest *);
extern void *vt_expect_node(xmlNodePtr, struct vtest *);

#endif

Snap of code generated in 'vt_gen_sandesh_expect.c'
--------------------------------------------------

/*
* Auto generated file
*/
#include <string.h>

#include <stdbool.h>

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>

#include <vr_types.h>
#include <vt_gen_lib.h>
#include <vtest.h>

bool
vr_nexthop_req_expect(xmlNodePtr node, struct vtest *test, void *buf)
{
bool result = true;
unsigned int list_size;
vr_nexthop_req *req = (vr_nexthop_req *)buf;

node = node->xmlChildrenNode;
while (node) {
if (!node->content || !strlen(node->content)) {
return NULL;
}

....
....

} else if (!strncmp(node->name, "nhr_label_list", strlen(node->content))) {
result = vt_gen_list_compare(req->nhr_label_list,
req->nhr_label_list_size, node->content, GEN_TYPE_U32);
}

if (!result)
return result;

node = node->next;
}

return result;
}


50 changes: 50 additions & 0 deletions utils/vtest/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#
# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
#
import os
Import('VRutilsEnv')
env = VRutilsEnv.Clone()
VTestEnv = env;

src_root = Dir('#').srcnode().abspath
build_root = Dir(env['TOP']).abspath
sandesh_file = src_root + '/vrouter/sandesh/vr.sandesh'
build_dir = build_root + '/vrouter/utils/vtest/'

system_header_path = GetOption('system-header-path')
if system_header_path:
env.Append(CPPPATH = system_header_path + '/include/')

env.Append(CPPPATH = ['./include', build_dir, '/usr/include/libxml2'])
xml_cpppath = os.popen('xml2-config --cflags | sed \'s/\-I//g\'').read()
#env.Append(CPPPATH = xml_cpppath)

# CFLAGS
env.Append(CCFLAGS = '-g')

env.Replace(LIBPATH = env['TOP_LIB'])
env.Append(LIBPATH = ['.', '../../sandesh'])
env.Replace(LIBS = ['sandesh-c', 'dp_sandesh_c', 'xml2'])

sandesh_gen = env.Program('sandesh_gen.c')

sandesh_gen_cmd = build_root + '/vrouter/utils/vtest/sandesh_gen' + ' ' + sandesh_file
sandesh_gen_output = env.Command('sandesh_gen_output', None,
sandesh_gen_cmd, chdir=build_dir)

vtest_src = [
'vt_main.c',
'vt_message.c',
'vt_gen_lib.c',
'vt_gen_message_modules.c',
'vt_gen_sandesh.c',
'vt_gen_sandesh_expect.c',
]


vtest = env.Program('vtest', vtest_src)
env.Requires(vtest, sandesh_gen_output)

# Local Variables:
# mode: python
# End:
36 changes: 36 additions & 0 deletions utils/vtest/example.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0"?>
<test>
<test_name>Interface test</test_name>
<message>
<vif>
<m_op>Add</m_op>
<vif_type>Virtual</vif_type>
<vif_index>4</vif_index>
<vif_vrf>0</vif_vrf>
<vif_mac>00:01:02:03:04:05</vif_mac>
<vif_mtu>1514</vif_mtu>
</vif>
<message_return>0</message_return>
</message>

<test_result>
<message>
<vif>
<m_op>Get</m_op>
<vif_index>4</vif_index>
</vif>
</message>
<message_return>0</message_return>
<message_expect>
<vif>
<vif_type>Virtual</vif_type>
<vif_index>4</vif_index>
<vif_vrf>0</vif_vrf>
<vif_mac>00:01:02:03:04:05</vif_mac>
<vif_mtu>1514</vif_mtu>
</vif>
</message_expect>
</test_result>

</test>

33 changes: 33 additions & 0 deletions utils/vtest/include/vt_gen_lib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* gen_lib.h --
*
* Copyright (c) 2015, Juniper Networks, Inc.
* All rights reserved
*/

#ifndef __GEN_LIB_H__
#define __GEN_LIB_H__

enum gen_types {
GEN_TYPE_U8,
GEN_TYPE_U16,
GEN_TYPE_U32,
GEN_TYPE_U64,
};

unsigned char *vt_gen_skip_space(unsigned char *);
unsigned char *vt_gen_reach_char(unsigned char *, unsigned char);
unsigned char *vt_gen_reach_space(unsigned char *);
bool vt_gen_byte_compare(uint8_t, uint8_t);
bool vt_gen_short_compare(uint16_t, uint16_t);
bool vt_gen_int_compare(unsigned int, unsigned int);
bool vt_gen_int64_compare(uint64_t, uint64_t);
bool vt_gen_flow_op_compare(int, unsigned char *);
int vt_gen_flow_op(unsigned char *);
bool vt_gen_op_compare(int, unsigned char *);
int vt_gen_op(unsigned char *);
void *vt_gen_list(unsigned char *, unsigned int, unsigned int *);
bool vt_gen_list_compare(void *, unsigned int, unsigned char *, unsigned int);
void *vt_gen_string(char *);

#endif /* __GEN_LIB_H__ */
30 changes: 30 additions & 0 deletions utils/vtest/include/vtest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* vtest.h --
*
* Copyright (c) 2015, Juniper Networks, Inc.
* All rights reserved
*/
#ifndef __VTEST_H__
#define __VTEST_H__

#define VT_PROG_NAME "vtest"
#define VT_MAX_TEST_NAME_LEN 128
#define VT_MAX_TEST_MODULE_NAME_LEN 128

struct vtest {
int vtest_return;
int vtest_iteration;
bool vtest_break;
unsigned char *vtest_name;
unsigned char *vtest_error_module;
};

struct vtest_module {
unsigned char *vt_name;
int (*vt_node)(xmlNodePtr, struct vtest *);
int (*vt_init)(void);
};

extern int vt_message(xmlNodePtr, struct vtest *);

#endif /* __VTEST_H__ */

0 comments on commit d74aa41

Please sign in to comment.