/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2010 Belledonne Communications SARL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#ifndef __USE_XOPEN
/*on Debian OS, time.h does declare strptime only if __USE_XOPEN is declared */
#define __USE_XOPEN
#endif
#include
#include "CUnit/Basic.h"
#include "linphonecore.h"
#include "private.h"
#include "liblinphone_tester.h"
#ifdef HAVE_ZLIB
#include
#endif
/*getline is POSIX 2008, not available on many systems.*/
#if defined(ANDROID) || defined(WIN32)
/* This code is public domain -- Will Hartung 4/9/09 */
size_t getline(char **lineptr, size_t *n, FILE *stream) {
char *bufptr = NULL;
char *p = bufptr;
size_t size;
int c;
if (lineptr == NULL) {
return -1;
}
if (stream == NULL) {
return -1;
}
if (n == NULL) {
return -1;
}
bufptr = *lineptr;
size = *n;
c = fgetc(stream);
if (c == EOF) {
return -1;
}
if (bufptr == NULL) {
bufptr = malloc(128);
if (bufptr == NULL) {
return -1;
}
size = 128;
}
p = bufptr;
while(c != EOF) {
if ((p - bufptr) > (size - 1)) {
size = size + 128;
bufptr = realloc(bufptr, size);
if (bufptr == NULL) {
return -1;
}
}
*p++ = c;
if (c == '\n') {
break;
}
c = fgetc(stream);
}
*p++ = '\0';
*lineptr = bufptr;
*n = size;
return p - bufptr - 1;
}
#endif
static LinphoneLogCollectionState old_collection_state;
void collect_init() {
old_collection_state = linphone_core_log_collection_enabled();
linphone_core_set_log_collection_path(liblinphone_tester_writable_dir_prefix);
}
void collect_cleanup(LinphoneCoreManager *marie) {
linphone_core_manager_destroy(marie);
linphone_core_enable_log_collection(old_collection_state);
linphone_core_reset_log_collection();
}
LinphoneCoreManager* setup(bool_t enable_logs) {
LinphoneCoreManager *marie;
int timeout = 300;
collect_init();
linphone_core_enable_log_collection(enable_logs);
marie = linphone_core_manager_new( "marie_rc");
// wait a few seconds to generate some traffic
while (--timeout){
// Generate some logs - error logs because we must ensure that
// even if user did not enable logs, we will see them
ms_error("(test error)Timeout in %d...", timeout);
}
return marie;
}
#if HAVE_ZLIB
/*returns uncompressed log file*/
FILE* gzuncompress(const char* filepath) {
gzFile file = gzopen(filepath, "rb");
FILE *output = NULL;
char *newname = ms_strdup_printf("%s.txt", filepath);
char buffer[512];
output = fopen(newname, "w+");
while (gzread(file, buffer, 511) > 0) {
fputs(buffer, output);
memset(buffer, 0, strlen(buffer));
}
CU_ASSERT_EQUAL(gzclose(file), Z_OK);
ms_free(newname);
fseek(output, 0, SEEK_SET);
return (FILE*)output;
}
#endif
time_t check_file(LinphoneCoreManager* mgr) {
time_t last_log = ms_time(NULL);
char* filepath = linphone_core_compress_log_collection(mgr->lc);
time_t time_curr = -1;
uint32_t timediff = 0;
FILE *file = NULL;
CU_ASSERT_PTR_NOT_NULL(filepath);
if (filepath != NULL) {
int line_count = 0;
char *line = NULL;
size_t line_size = 256;
#ifndef WIN32
struct tm tm_curr;
time_t time_prev = -1;
#endif
#if HAVE_ZLIB
// 0) if zlib is enabled, we must decompress the file first
file = gzuncompress(filepath);
#else
file = fopen(filepath, "r");
#endif
// 1) expect to find folder name in filename path
CU_ASSERT_PTR_NOT_NULL(strstr(filepath, liblinphone_tester_writable_dir_prefix));
// 2) check file contents
while (getline(&line, &line_size, file) != -1) {
// a) there should be at least 25 lines
++line_count;
#ifndef WIN32
// b) logs should be ordered by date (format: 2014-11-04 15:22:12:606)
if (strlen(line) > 24) {
char date[24] = {'\0'};
memcpy(date, line, 23);
if (strptime(date, "%Y-%m-%d %H:%M:%S", &tm_curr) != NULL) {
time_curr = mktime(&tm_curr);
CU_ASSERT_TRUE(time_curr >= time_prev);
time_prev = time_curr;
}
}
#else
ms_warning("strptime() not available for this platform, test is incomplete.");
#endif
}
CU_ASSERT_TRUE(line_count > 25);
free(line);
fclose(file);
ms_free(filepath);
timediff = labs((long int)time_curr - (long int)last_log);
CU_ASSERT_TRUE( timediff <= 1 );
if( !(timediff <= 1) ){
ms_error("time_curr: %ld, last_log: %ld timediff: %d", time_curr, last_log, timediff );
}
}
// return latest time in file
return time_curr;
}
static void collect_files_disabled() {
LinphoneCoreManager* marie = setup(FALSE);
CU_ASSERT_PTR_NULL(linphone_core_compress_log_collection(marie->lc));
collect_cleanup(marie);
}
static void collect_files_filled() {
LinphoneCoreManager* marie = setup(TRUE);
check_file(marie);
collect_cleanup(marie);
}
static void collect_files_small_size() {
LinphoneCoreManager* marie = setup(TRUE);
linphone_core_set_log_collection_max_file_size(5000);
check_file(marie);
collect_cleanup(marie);
}
static void collect_files_changing_size() {
LinphoneCoreManager* marie = setup(TRUE);
int waiting = 100;
check_file(marie);
linphone_core_set_log_collection_max_file_size(5000);
// Generate some logs
while (--waiting) ms_error("(test error)Waiting %d...", waiting);
check_file(marie);
collect_cleanup(marie);
}
test_t log_collection_tests[] = {
{ "No file when disabled", collect_files_disabled},
{ "Collect files filled when enabled", collect_files_filled},
{ "Logs collected into small file", collect_files_small_size},
{ "Logs collected when decreasing max size", collect_files_changing_size},
};
test_suite_t log_collection_test_suite = {
"LogCollection",
NULL,
NULL,
sizeof(log_collection_tests) / sizeof(log_collection_tests[0]),
log_collection_tests
};