Commit 38ee1f57 authored by Nevadita's avatar Nevadita

wfadatad: Adding the framework for ci cd

parent c258f86a
Pipeline #1308 failed
include:
- project: 'iopsys/gitlab-ci-pipeline'
file: '/static-code-analysis.yml'
stages:
- static_code_analysis
variables:
DEBUG: 'TRUE'
SOURCE_FOLDER: "src"
run_unit_test:
stage: unit_test
image: iopsys/code-analysis:0.20
allow_failure: true
script:
- "./gitlab-ci/setup.sh"
- "./gitlab-ci/unit-test.sh"
artifacts:
when: always
paths:
- unit-test-coverage.xml
- timestamp.log
run_api_test:
stage: api_test
image: iopsys/code-analysis:0.20
allow_failure: true
script:
- "./gitlab-ci/setup.sh"
- "./gitlab-ci/functional-api-test.sh"
artifacts:
when: always
reports:
junit: ./report/tap.xml
paths:
- api-test-coverage.xml
- api-test-memory-report.xml
- timestamp.log
#!/bin/bash
echo "$0 preparation script"
pwd
make coverage -C ./
supervisorctl status all
supervisorctl update
supervisorctl restart all
sleep 3
supervisorctl status all
# run API validation
ubus-api-validator -d ./test/api/json/ > ./api-result.log
ret=$?
supervisorctl stop all
supervisorctl status
#report part
gcovr -r . --xml -o ./api-test-coverage.xml
gcovr -r .
cp ./memory-report.xml ./api-test-memory-report.xml
tap-junit --input ./api-result.log --output report
date +%s > timestamp.log
echo "$0 exit status ${ret}"
exit ${ret}
[program:ubusd]
command=/bin/bash -c "/usr/sbin/ubusd"
[program:uspd]
command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=memory-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes /builds/iopsys/wfadatad/wfa_delm"
/*
* alloctrace.c - trace alloc and free calls
*
* Copyright (C) 2019 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <dlfcn.h>
#include "alloctrace.h"
static void *(*_malloc)(size_t);
static void (*_free)(void *);
static FILE *tracefile;
static void fprintf_timestamp_prefix(FILE *f)
{
time_t now = time(NULL);
struct tm *tm_now = localtime(&now);
const char *tm_fmt = "[%d-%02d-%02d %02d:%02d:%02d] ";
fprintf(f, tm_fmt,
tm_now->tm_year + 1900,
tm_now->tm_mon + 1,
tm_now->tm_mday,
tm_now->tm_hour,
tm_now->tm_min,
tm_now->tm_sec);
}
void init_alloctrace(const char *prog)
{
char f[128] = {0};
if (trace_alloc) {
sprintf(f, "/tmp/%s_mtrace.log", prog);
tracefile = fopen(f, "w+");
if (tracefile)
fprintf(stderr, "Successfully opened '%s'\n", f);
}
_malloc = dlsym(RTLD_NEXT, "malloc");
if (NULL == _malloc) {
fprintf(tracefile, "Error! dlsym: %s\n", dlerror());
}
_free = dlsym(RTLD_NEXT, "free");
if (NULL == _free) {
fprintf(tracefile, "Error! dlsym: %s\n", dlerror());
}
if (trace_alloc && tracefile) {
fprintf_timestamp_prefix(tracefile);
fprintf(tracefile, "Begin\n");
}
}
void exit_alloctrace(void)
{
if (trace_alloc && tracefile) {
fprintf_timestamp_prefix(tracefile);
fprintf(tracefile, "End\n");
fclose(tracefile);
}
}
void dbg_free(void *ptr, const char *by, const int lno)
{
void *caller = __builtin_return_address(0);
_free(ptr);
if (trace_alloc && tracefile) {
fprintf_timestamp_prefix(tracefile);
fprintf(tracefile,
"free : %32s():%6d [& = %12p] ptr = %12p\n",
by, lno, caller, ptr);
fflush(tracefile);
}
}
void *dbg_malloc(size_t size, const char *by, const int lno)
{
void *ptr = NULL;
void *caller = __builtin_return_address(0);
ptr = _malloc(size);
if (trace_alloc && tracefile && ptr) {
fprintf_timestamp_prefix(tracefile);
fprintf(tracefile,
"malloc: %32s():%6d [& = %12p] ptr = %12p size = %zu\n",
by, lno, caller, ptr, size);
fflush(tracefile);
}
return ptr;
}
void *dbg_calloc(size_t nmemb, size_t size, const char *by, const int lno)
{
void *ptr = NULL;
void *caller = __builtin_return_address(0);
ptr = _malloc(nmemb * size);
if (ptr)
memset(ptr, 0, nmemb * size);
if (trace_alloc && tracefile && ptr) {
fprintf_timestamp_prefix(tracefile);
fprintf(tracefile,
"calloc: %32s():%6d [& = %12p] ptr = %12p size = %zu\n",
by, lno, caller, ptr, size);
fflush(tracefile);
}
return ptr;
}
/*
* alloctrace.h - trace heap memory alloc and free
*
* Copyright (C) 2019 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#ifndef ALLOCTRACE_H
#define ALLOCTRACE_H
extern int trace_alloc;
#ifdef TRACE_ALLOC
extern void init_alloctrace(const char *progname);
extern void exit_alloctrace(void);
extern void *dbg_malloc(size_t size, const char *by, const int lno);
extern void dbg_free(void *ptr, const char *by, const int lno);
extern void *dbg_calloc(size_t nmemb, size_t size, const char *by, const int lno);
#define malloc(s) dbg_malloc(s, __func__, __LINE__)
#define calloc(n, s) dbg_calloc(n, s, __func__, __LINE__)
#define free(p) dbg_free(p, __func__, __LINE__)
#else
static inline void init_alloctrace(const char *progname)
{
}
static inline void exit_alloctrace(void)
{
}
#define dbg_malloc
#define dbg_free
#define dbg_calloc
#endif /* TRACE_ALLOC */
#endif /* ALLOCTRACE_H */
/*
* debug.c - for debug and logging
*
* Copyright (C) 2019 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include "debug.h"
static FILE *outfile = NULL;
static int ffd;
extern const char *outfile_path;
extern const char *PROG_NAME;
extern int verbose;
extern bool syslogging;
extern bool usefifo;
static const int syslog_level[] = { LOG_ERR, LOG_WARNING, LOG_INFO, LOG_DEBUG };
void start_logging(void)
{
if (syslogging)
openlog(PROG_NAME, 0, LOG_DAEMON);
if (!outfile) {
if (outfile_path) {
if (usefifo) {
struct stat st;
int rfd;
if (stat(outfile_path, &st))
unlink(outfile_path);
mkfifo(outfile_path, 0600);
if (stat(outfile_path, &st) == -1 ||
!S_ISFIFO(st.st_mode))
return;
rfd = open(outfile_path, O_RDONLY | O_NONBLOCK);
if (rfd) {
ffd = open(outfile_path, O_WRONLY | O_NONBLOCK);
close(rfd);
}
} else {
outfile = fopen(outfile_path, "w+");
}
} else {
outfile = stderr;
}
}
}
void stop_logging(void)
{
if (syslogging)
closelog();
if (outfile)
fclose(outfile);
if (ffd) {
close(ffd);
unlink(outfile_path);
}
}
void log_message(int level, const char *fmt, ...)
{
va_list args;
if (level > verbose) {
if (usefifo && ffd) {
time_t now = time(NULL);
struct tm *tm_now = localtime(&now);
const char *tm_fmt = "[%d-%02d-%02d %02d:%02d:%02d] ";
va_start(args, fmt);
dprintf(ffd, tm_fmt,
tm_now->tm_year + 1900,
tm_now->tm_mon + 1,
tm_now->tm_mday,
tm_now->tm_hour,
tm_now->tm_min,
tm_now->tm_sec);
vdprintf(ffd, fmt, args);
va_end(args);
}
return;
}
va_start(args, fmt);
if (syslogging && level >= 0)
vsyslog(syslog_level[level], fmt, args);
if (outfile)
vfprintf(outfile, fmt, args);
if (usefifo && ffd)
vdprintf(ffd, fmt, args);
va_end(args);
}
void dump(unsigned char *buf, int len, char *label)
{
int i;
if (label)
printf("---- %s ----", label);
for (i = 0; i < len; i++) {
if (!(i % 4))
printf(" ");
if (!(i % 16))
printf("\n ");
printf("%02x ", buf[i] & 0xff);
}
if (label)
printf("\n--------------\n");
}
/*
* debug.h - debug and logging header file
*
* Copyright (C) 2019 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#ifndef DEBUG_H
#define DEBUG_H
#include "alloctrace.h"
void start_logging(void);
void stop_logging(void);
void log_message(int level, const char *fmt, ...);
#define DEBUG_COLOR 1
#ifdef DEBUG_COLOR
#define red "\033[0;31m"
#define green "\033[0;32m"
#define yellow "\033[1;33m"
#define brown "\033[0;33m"
#define blue "\033[0;34m"
#define magenta "\033[0;35m"
#define bgred "\033[48;5;196m"
#define bggreen "\033[48;5;046m"
#define bgyellow "\033[48;5;226m"
#define bgblue "\033[48;5;037m"
#define nocl "\033[0m"
#define logrec(fmt, ...) log_message(-1, __VA_ARGS__)
#define err(fmt, ...) log_message(0, red fmt nocl, ## __VA_ARGS__)
#define warn(fmt, ...) log_message(1, red fmt nocl, ## __VA_ARGS__)
#define info(fmt, ...) log_message(2, blue fmt nocl, ## __VA_ARGS__)
#define dbg(fmt, ...) log_message(3, nocl fmt nocl, ## __VA_ARGS__)
#define trace(fmt, ...) log_message(4, fmt, ## __VA_ARGS__)
#define trace_cmd(fmt, ...) log_message(4, brown fmt nocl, ## __VA_ARGS__)
#define loud(fmt, ...) log_message(5, fmt, ## __VA_ARGS__)
#else
#define logrec(...) log_message(-1, __VA_ARGS__)
#define err(...) log_message(0, __VA_ARGS__)
#define warn(...) log_message(1, __VA_ARGS__)
#define info(...) log_message(2, __VA_ARGS__)
#define dbg(...) log_message(3, __VA_ARGS__)
#define trace(...) log_message(4, __VA_ARGS__)
#define trace_cmd(...) log_message(4, __VA_ARGS__)
#define loud(...) log_message(5, __VA_ARGS__)
#endif /* DEBUG_COLOR */
void dump(unsigned char *buf, int len, char *label);
#endif /* DEBUG_H */
/*
* hlist.h - stripped down version of hash list implementation using
* singly linked list.
* Doubly linked list is wastage of space for big hash-tables. If cost of
* iterating a hash list is significant, it means the hash function is NOT
* formulated well and should be revisited.
*
* Copyright (C) 2019 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#ifndef _HLIST_H
#define _HLIST_H
struct hlist_node {
struct hlist_node *next;
};
struct hlist_head {
struct hlist_node *first;
};
#define HLIST_HEAD_INIT(name) { &(name) }
#define HLIST_HEAD(name) struct hlist_head name = HLIST_HEAD_INIT(name)
static inline void INIT_HLIST_HEAD(struct hlist_head *h)
{
h->first = NULL;
}
static inline void INIT_HLIST_NODE(struct hlist_node *n)
{
n->next = NULL;
}
static inline int hlist_empty(const struct hlist_head *h)
{
return !h->first;
}
static inline void __hlist_del(struct hlist_node *prev, struct hlist_node *n)
{
prev->next = n->next;
n->next = NULL;
}
static inline void hlist_del(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *p;
if (h->first == n) {
h->first = NULL;
n->next = NULL;
return;
}
for (p = h->first; p; p = p->next) {
if (p->next == n)
__hlist_del(p, n);
}
}
static inline void _hlist_add(struct hlist_node *_new, struct hlist_head *h)
{
_new->next = h->first;
h->first = _new;
}
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
_hlist_add(n, h);
}
#define hlist_for_each(pos, head) \
for (pos = (head)->first; pos ; pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
#define hlist_entry(ptr, type, member) container_of(ptr, type, member)
#define hlist_entry_safe(ptr, type, member) \
({ typeof(ptr) ____ptr = (ptr); \
____ptr ? hlist_entry(____ptr, type, member) : NULL; \
})
#define hlist_for_each_entry(pos, head, member) \
for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member); \
pos; \
pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
#define hlist_for_each_entry_safe(pos, n, head, member) \
for (pos = hlist_entry_safe((head)->first, typeof(*pos), member); \
pos && ({ n = pos->member.next; 1; }); \
pos = hlist_entry_safe(n, typeof(*pos), member))
#endif /* _HLIST_H */
/*
* liblist.c - implements list utility functions
*
* Copyright (C) 2018 iopsys Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#include <libubox/list.h>
#define list_singular(l) ((l)->next->next == (l))
int list_split(struct list_head *head, struct list_head *second)
{
struct list_head *fast, *slow;
int cnt = 0;
if (list_empty(head) || list_singular(head))
return cnt;
fast = head;
list_for_each(slow, head) {
cnt++;
fast = fast->next;
if (fast->next == head)
break;
fast = fast->next;
if (fast->next == head)
break;
}
second->next = slow->next;
second->prev = fast;
fast->next = second;
slow->next->prev = second;
head->prev = slow;
slow->next = head;
return cnt;
}
void list_merge(void *priv, struct list_head *a, struct list_head *b,
int (*cmp)(void *priv, struct list_head *x, struct list_head *y))
{
struct list_head *p;
/* trivial when one sublist is empty */
if (list_empty(b))
return;
if (list_empty(a)) {
while (!list_empty(b))
list_move_tail(b->next, a);
return;
}
p = a;
while (p->next != a && !list_empty(b)) {
if (cmp(priv, p->next, b->next) <= 0)
p = p->next;
else
list_move(b->next, p);
}
/* merge leftover from right sublist, if any */
if (p->next == a) {
while (!list_empty(b))
list_move_tail(b->next, a);
}
}
void merge_sort(void *priv, struct list_head *head,
int (*cmp)(void *priv, struct list_head *x, struct list_head *y))
{
struct list_head right;
INIT_LIST_HEAD(&right);
if (list_empty(head) || list_singular(head))
return;
list_split(head, &right);
merge_sort(priv, head, cmp);
merge_sort(priv, &right, cmp);
list_merge(priv, head, &right, cmp);
}
/*
* liblist.h - list utility functions header file
*
* Copyright (C) 2018 iopsys Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
*/
#ifndef LIBLIST_H
#define LIBLIST_H
#include <libubox/list.h>
/**
* list_split - split a list into two sublists.
* @head: pointer to list head
* @second: pointer to the right sublist
*/
int list_split(struct list_head *head, struct list_head *second);
/**
* list_merge - merge two lists.
* @priv: opaque private data passed by caller
* @a: pointer to first list
* @b: pointer to second list
* @cmp: comparator function pointer, which decides relative ordering
* between two list elements during the merge
*/
void list_merge(void *priv, struct list_head *a, struct list_head *b,
int (*cmp)(void *priv, struct list_head *x, struct list_head *y));
/**
* merge_sort - merge sort a list.
* @priv: opaque private data passed by caller
* @head: pointer to list head
* @cmp: comparator function pointer, which decides relative ordering
* between two list elements during the sort.
*/
void merge_sort(void *priv, struct list_head *head,
int (*cmp)(void *priv, struct list_head *x, struct list_head *y));
#ifndef list_sort
#define list_sort merge_sort
#endif
#endif /* LIBLIST_H */
/*
* map_module.h - multi-ap module(s) registration API header.
*
* Copyright (C) 2020 iopsys Software Solutions AB. All rights reserved.
*
* Author: anjan.chanda@iopsys.eu
*
* See LICENSE file for license related information.
*
*/
#ifndef MAP_MODULE_H
#define MAP_MODULE_H
#include <stdint.h>
#include <stdbool.h>
#include <linux/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/* wifi-agents and wifi-controller will implement the multiap CMDU handler
* function. Based on the cmdu_type, appropriate action will be taken by
* wifi-agents and wifi-controller.
* 'msg' points to the TLVs buffer, as defined in the multiap specification
* and in that order.
* 'msglen' is length of the 'msg'.
*/
typedef int (*cmdu_handler_t)(uint16_t cmdu_type, void *msg, size_t msglen);
typedef uint8_t map_module_id_t[32];
enum map_role {
MAP_ROLE_AGENT = 0x1,
MAP_ROLE_CONTROLLER = 0x2
};
enum map_profile {