Skip to content
Snippets Groups Projects
Commit b620082e authored by Konstantin Osipov's avatar Konstantin Osipov
Browse files

Implement a simple unit testing framework. Add the first unit test.

Extend queue.h with STAILQ_SPLICE and STAILQ_REVERSE.
Test the new functions in a simple unit testing framework.
parent a263e05e
No related branches found
No related tags found
No related merge requests found
......@@ -13,6 +13,7 @@ test/lib/*.pyc
test/lib/*/*.pyc
test/box/protocol
test/box/connector
test/unit/queue
Makefile
CMakeFiles
CMakeCache.txt
......
......@@ -4,6 +4,7 @@ add_custom_target(test
add_custom_target(test-force
COMMAND ${PROJECT_SOURCE_DIR}/test/run.sh --builddir=${PROJECT_BINARY_DIR} --force --vardir=${PROJECT_BINARY_DIR}/test/var)
add_subdirectory(unit)
add_subdirectory(box)
add_subdirectory(connector_c)
......
......@@ -177,7 +177,7 @@ class Server(object):
if start_and_exit != None: self.start_and_exit = start_and_exit
if gdb != None: self.gdb = gdb
if valgrind != None: self.valgrind = valgrind
self.debug = self.test_debug()
self.debug = self.test_debug()
if self.is_started:
if not silent:
......@@ -269,7 +269,7 @@ class Server(object):
def test_option_get(self, show, option_list_str):
args = [self.binary] + option_list_str.split()
if show:
if show:
print " ".join([os.path.basename(self.binary)] + args[1:])
output = subprocess.Popen(args,
cwd = self.vardir,
......@@ -282,7 +282,7 @@ class Server(object):
def test_debug(self):
output = self.test_option_get(False, "-V")
if re.search("-Debug", output):
if re.search("-Debug", output):
return True
return False
......
from server import Server
import subprocess
import sys
import os
class UnittestServer(Server):
"""A dummy server implementation for unit test suite"""
def __new__(cls, core="unittest", module="dummy"):
return Server.__new__(cls)
def __init__(self, core="unittest", module="dummy"):
Server.__init__(self, core, module)
self.debug = False
def configure(self, config):
pass
def deploy(self, config=None, binary=None, vardir=None,
mem=None, start_and_exit=None, gdb=None, valgrind=None,
valgrind_sup=None, init_lua=None, silent=True, need_init=True):
self.vardir = vardir
def run_test(name):
p = subprocess.Popen([os.path.join(self.builddir, "test/unit", name)], stdout=subprocess.PIPE)
p.wait()
for line in p.stdout.readlines():
sys.stdout.write(line)
self.run_test = run_test
def start(self):
pass
def find_exe(self, builddir, silent=False):
self.builddir = builddir
def init(self):
pass
add_executable(queue queue.c)
/*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "third_party/queue.h"
#include "unit.h"
#include <stdio.h>
#include <assert.h>
struct elem
{
STAILQ_ENTRY(elem) entry;
int val;
};
STAILQ_HEAD(elem_queue, elem);
const char *
queue2str(struct elem_queue *queue)
{
static char buf[1024];
buf[0] = '\0';
struct elem *elem;
int n = 0;
STAILQ_FOREACH(elem, queue, entry) {
n += snprintf(buf + n, sizeof(buf) - n - 1, "%d ", elem->val);
}
return buf;
}
/** Test a queue with 0 elements. */
void test0()
{
header();
struct elem_queue queue = STAILQ_HEAD_INITIALIZER(queue);
printf("Initialized: %s\n", queue2str(&queue));
STAILQ_INIT(&queue);
printf("STAILQ_INIT: %s\n", queue2str(&queue));
STAILQ_REVERSE(&queue, elem, entry);
printf("STAILQ_REVERSE: %s\n", queue2str(&queue));
footer();
}
/** Test a queue with 1 element. */
void test1()
{
header();
struct elem el1;
struct elem_queue queue = STAILQ_HEAD_INITIALIZER(queue);
el1.val = 1;
STAILQ_INSERT_TAIL(&queue, &el1, entry);
printf("STAILQ_INIT: %s\n", queue2str(&queue));
STAILQ_REVERSE(&queue, elem, entry);
printf("STAILQ_REVERSE: %s\n", queue2str(&queue));
footer();
}
void test2()
{
header();
struct elem el1, el2;
struct elem_queue queue = STAILQ_HEAD_INITIALIZER(queue);
el1.val = 1;
el2.val = 2;
STAILQ_INSERT_TAIL(&queue, &el1, entry);
STAILQ_INSERT_TAIL(&queue, &el2, entry);
printf("STAILQ_INIT: %s\n", queue2str(&queue));
STAILQ_REVERSE(&queue, elem, entry);
printf("STAILQ_REVERSE: %s\n", queue2str(&queue));
footer();
}
void test3()
{
header();
struct elem el1, el2, el3;
struct elem_queue queue = STAILQ_HEAD_INITIALIZER(queue);
el1.val = 1;
el2.val = 2;
el3.val = 3;
STAILQ_INSERT_TAIL(&queue, &el1, entry);
STAILQ_INSERT_TAIL(&queue, &el2, entry);
STAILQ_INSERT_TAIL(&queue, &el3, entry);
printf("STAILQ_INIT: %s\n", queue2str(&queue));
STAILQ_REVERSE(&queue, elem, entry);
printf("STAILQ_REVERSE: %s\n", queue2str(&queue));
footer();
}
void test_splice()
{
header();
struct elem el1, el2, el3;
struct elem_queue queue1 = STAILQ_HEAD_INITIALIZER(queue1);
struct elem_queue queue2 = STAILQ_HEAD_INITIALIZER(queue2);
STAILQ_SPLICE(&queue1, STAILQ_FIRST(&queue1), entry, &queue2);
printf("q1: %s\n", queue2str(&queue1));
printf("q2: %s\n", queue2str(&queue2));
STAILQ_SPLICE(&queue2, STAILQ_FIRST(&queue2), entry, &queue1);
printf("q1: %s\n", queue2str(&queue1));
printf("q2: %s\n", queue2str(&queue2));
el1.val = 1;
el2.val = 2;
el3.val = 3;
STAILQ_INSERT_TAIL(&queue1, &el1, entry);
STAILQ_INSERT_TAIL(&queue1, &el2, entry);
STAILQ_INSERT_TAIL(&queue1, &el3, entry);
printf("STAILQ_INIT: %s\n", queue2str(&queue1));
STAILQ_SPLICE(&queue1, STAILQ_FIRST(&queue1), entry, &queue2);
printf("q1: %s\n", queue2str(&queue1));
printf("q2: %s\n", queue2str(&queue2));
STAILQ_SPLICE(&queue2, STAILQ_FIRST(&queue2), entry, &queue1);
printf("q1: %s\n", queue2str(&queue1));
printf("q2: %s\n", queue2str(&queue2));
STAILQ_SPLICE(&queue1, STAILQ_NEXT(STAILQ_FIRST(&queue1), entry),
entry, &queue2);
printf("q1: %s\n", queue2str(&queue1));
printf("q2: %s\n", queue2str(&queue2));
STAILQ_SPLICE(&queue2, STAILQ_NEXT(STAILQ_FIRST(&queue2), entry),
entry, &queue1);
printf("q1: %s\n", queue2str(&queue1));
printf("q2: %s\n", queue2str(&queue2));
STAILQ_SPLICE(&queue2, STAILQ_FIRST(&queue2), entry, &queue1);
printf("q1: %s\n", queue2str(&queue1));
printf("q2: %s\n", queue2str(&queue2));
STAILQ_SPLICE(&queue2, STAILQ_FIRST(&queue2), entry, &queue1);
printf("q1: %s\n", queue2str(&queue1));
printf("q2: %s\n", queue2str(&queue2));
footer();
}
int main()
{
test0();
test1();
test2();
test3();
test_splice();
return 0;
}
*** test0 ***
Initialized:
STAILQ_INIT:
STAILQ_REVERSE:
*** test0: done ***
*** test1 ***
STAILQ_INIT: 1
STAILQ_REVERSE: 1
*** test1: done ***
*** test2 ***
STAILQ_INIT: 1 2
STAILQ_REVERSE: 2 1
*** test2: done ***
*** test3 ***
STAILQ_INIT: 1 2 3
STAILQ_REVERSE: 3 2 1
*** test3: done ***
*** test_splice ***
q1:
q2:
q1:
q2:
STAILQ_INIT: 1 2 3
q1:
q2: 1 2 3
q1: 1 2 3
q2:
q1: 1
q2: 2 3
q1: 1 3
q2: 2
q1: 1 3 2
q2:
q1: 1 3 2
q2:
*** test_splice: done ***
\ No newline at end of file
run_test("queue")
[default]
core = unittest
module = box
description = unit tests
config = tarantool.cfg
# put disabled tests here
#disabled = xlog.test
# put disabled in valgrind test here
#valgrind_disabled = admin_coredump.test
#release_disabled = errinj.test
#ifndef INCLUDES_TARANTOOL_TEST_UNIT_H
#define INCLUDES_TARANTOOL_TEST_UNIT_H
/*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define header() printf("\t*** %s ***\n", __FUNCTION__)
#define footer() printf("\t*** %s: done ***\n ", __FUNCTION__)
#endif /* INCLUDES_TARANTOOL_TEST_UNIT_H */
......@@ -304,6 +304,31 @@ struct { \
(head)->stqh_last = &STAILQ_FIRST((head)); \
} while (0)
/* Reverse a list in-place. */
#define STAILQ_REVERSE(head, type, member) do { \
struct type *elem = STAILQ_FIRST(head), *next; \
STAILQ_INIT(head); \
while (elem) { \
next = STAILQ_NEXT(elem, member); \
STAILQ_INSERT_HEAD(head, elem, member); \
elem = next; \
} \
} while (0)
/* Concat all members of head1 starting from elem to the end of head2. */
#define STAILQ_SPLICE(head1, elem, member, head2) do { \
if (elem) { \
*(head2)->stqh_last = (elem); \
(head2)->stqh_last = (head1)->stqh_last; \
(head1)->stqh_last = &STAILQ_FIRST(head1); \
while (*(head1)->stqh_last != (elem)) { \
(head1)->stqh_last = &STAILQ_NEXT( \
*(head1)->stqh_last, member); \
} \
*(head1)->stqh_last = NULL; \
} \
} while (0)
/*
* List declarations.
*/
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment