summaryrefslogtreecommitdiff
path: root/test/bt-utils.c
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2016-11-09 16:36:34 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2016-11-09 16:36:34 +0100
commit9b0a0ba9e671d9134b93c33ab73ccccb352acafa (patch)
tree2a3b007b698c02c72c7bae25d3c7cae6293cd36f /test/bt-utils.c
parent8860e991f6650e47cfe6c1af595fe4fe92a4edfd (diff)
Unit Testing for BIRD
- Unit Testing Framework (BirdTest) - Integration of BirdTest into the BIRD build system - Tests for several BIRD modules Based on squashed Pavel Tvrdik's int-test branch, updated for current int-new branch.
Diffstat (limited to 'test/bt-utils.c')
-rw-r--r--test/bt-utils.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/test/bt-utils.c b/test/bt-utils.c
new file mode 100644
index 00000000..aaeb77b8
--- /dev/null
+++ b/test/bt-utils.c
@@ -0,0 +1,223 @@
+/*
+ * BIRD Test -- Utils for testing parsing configuration file
+ *
+ * (c) 2015 CZ.NIC z.s.p.o.
+ *
+ * Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "test/birdtest.h"
+#include "test/bt-utils.h"
+
+#include "nest/bird.h"
+#include "nest/route.h"
+#include "nest/protocol.h"
+
+#include "sysdep/unix/unix.h"
+#include "sysdep/unix/krt.h"
+
+#include "nest/iface.h"
+#include "nest/locks.h"
+
+#include "filter/filter.h"
+
+#define BETWEEN(a, b, c) (((a) >= (b)) && ((a) <= (c)))
+
+static const byte *bt_config_parse_pos;
+static uint bt_config_parse_remain_len;
+
+/* This is cf_read_hook for hard-coded text configuration */
+static int
+cf_static_read(byte *dest, uint max_len, int fd UNUSED)
+{
+ if (max_len > bt_config_parse_remain_len)
+ max_len = bt_config_parse_remain_len;
+ memcpy(dest, bt_config_parse_pos, max_len);
+ bt_config_parse_pos += max_len;
+ bt_config_parse_remain_len -= max_len;
+ return max_len;
+}
+
+/* This is cf_read_hook for reading configuration files,
+ * function is copied from main.c, cf_read() */
+static int
+cf_file_read(byte *dest, uint max_len, int fd)
+{
+ int l = read(fd, dest, max_len);
+ if (l < 0)
+ cf_error("Read error");
+ return l;
+}
+
+void
+bt_bird_init(void)
+{
+ if(bt_verbose)
+ log_init_debug("");
+ log_switch(bt_verbose != 0, NULL, NULL);
+
+ resource_init();
+ olock_init();
+ io_init();
+ rt_init();
+ if_init();
+ config_init();
+
+ protos_build();
+ proto_build(&proto_unix_kernel);
+ proto_build(&proto_unix_iface);
+}
+
+void bt_bird_cleanup(void)
+{
+ for (int i = 0; i < EAP_MAX; i++)
+ attr_class_to_protocol[i] = NULL;
+
+ config = new_config = NULL;
+}
+
+static char *
+bt_load_file(const char *filename, int quiet)
+{
+ FILE *f = fopen(filename, "rb");
+ if (!quiet)
+ bt_assert_msg(f != NULL, "Open %s", filename);
+
+ if (f == NULL)
+ return NULL;
+
+ fseek(f, 0, SEEK_END);
+ long file_size_ = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ if (file_size_ < 0)
+ return NULL;
+
+ size_t file_size = file_size_;
+ size_t read_size = 0;
+
+ char *file_body = mb_allocz(&root_pool, file_size+1);
+
+ /* XXX: copied from cf-lex.c */
+ errno=0;
+ while ((read_size += fread(file_body+read_size, 1, file_size-read_size, f)) != file_size && ferror(f))
+ {
+ bt_debug("iteration \n");
+ if(errno != EINTR)
+ {
+ bt_abort_msg("errno: %d", errno);
+ break;
+ }
+ errno=0;
+ clearerr(f);
+ }
+ fclose(f);
+
+ if (!quiet)
+ bt_assert_msg(read_size == file_size, "Read %s", filename);
+
+ return file_body;
+}
+
+static void
+bt_show_cfg_error(const struct config *cfg)
+{
+ int lino = 0;
+ int lino_delta = 5;
+ int lino_err = cfg->err_lino;
+
+ const char *str = bt_load_file(cfg->err_file_name, 1);
+
+ while (str && *str)
+ {
+ lino++;
+ if (BETWEEN(lino, lino_err - lino_delta, lino_err + lino_delta))
+ bt_debug("%4u%s", lino, (lino_err == lino ? " >> " : " "));
+ do
+ {
+ if (BETWEEN(lino, lino_err - lino_delta, lino_err + lino_delta))
+ bt_debug("%c", *str);
+ } while (*str && *(str++) != '\n');
+ }
+ bt_debug("\n");
+}
+
+static struct config *
+bt_config_parse__(struct config *cfg)
+{
+ bt_assert_msg(config_parse(cfg) == 1, "Parse %s", cfg->file_name);
+
+ if (cfg->err_msg)
+ {
+ bt_debug("Parse error %s, line %d: %s\n", cfg->err_file_name, cfg->err_lino, cfg->err_msg);
+ bt_show_cfg_error(cfg);
+ return NULL;
+ }
+
+ config_commit(cfg, RECONFIG_HARD, 0);
+ new_config = cfg;
+
+ return cfg;
+}
+
+struct config *
+bt_config_parse(const char *cfg_str)
+{
+ struct config *cfg = config_alloc("configuration");
+
+ bt_config_parse_pos = cfg_str;
+ bt_config_parse_remain_len = strlen(cfg_str);
+ cf_read_hook = cf_static_read;
+
+ return bt_config_parse__(cfg);
+}
+
+struct config *
+bt_config_file_parse(const char *filepath)
+{
+ struct config *cfg = config_alloc(filepath);
+
+ cfg->file_fd = open(filepath, O_RDONLY);
+ bt_assert_msg(cfg->file_fd > 0, "Open %s", filepath);
+ if (cfg->file_fd < 0)
+ return NULL;
+
+ cf_read_hook = cf_file_read;
+
+ return bt_config_parse__(cfg);
+}
+
+/*
+ * Returns @base raised to the power of @power.
+ */
+uint
+bt_naive_pow(uint base, uint power)
+{
+ uint result = 1;
+ uint i;
+ for (i = 0; i < power; i++)
+ result *= base;
+ return result;
+}
+
+/**
+ * bytes_to_hex - transform data into hexadecimal representation
+ * @buf: preallocated string buffer
+ * @in_data: data for transformation
+ * @size: the length of @in_data
+ *
+ * This function transforms @in_data of length @size into hexadecimal
+ * representation and writes it into @buf.
+ */
+void
+bt_bytes_to_hex(char *buf, const byte *in_data, size_t size)
+{
+ size_t i;
+ for(i = 0; i < size; i++)
+ sprintf(buf + i*2, "%02x", in_data[i]);
+}
+