log_collection_tester.c 6.14 KB
Newer Older
1 2
/*
	belle-sip - SIP (RFC3261) library.
3
	Copyright (C) 2010  Belledonne Communications SARL
4

5 6 7 8
	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.
9

10 11 12 13
	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.
14

15 16
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 18 19
*/

#include <stdio.h>
20 21 22 23
#ifndef __USE_XOPEN
	/*on Debian OS, time.h does declare strptime only if __USE_XOPEN is declared */
	#define __USE_XOPEN
#endif
24 25 26 27 28 29
#include <time.h>
#include "CUnit/Basic.h"
#include "linphonecore.h"
#include "private.h"
#include "liblinphone_tester.h"

30 31 32 33
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif

34

35 36
/*getline is POSIX 2008, not available on many systems.*/
#if defined(ANDROID) || defined(WIN32)
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
/* 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

91 92 93 94 95 96 97 98 99 100 101 102 103
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();
}

104 105
LinphoneCoreManager* setup(bool_t enable_logs)  {
	LinphoneCoreManager *marie;
106 107
	int timeout = 300;

108
	collect_init();
Simon Morlat's avatar
Simon Morlat committed
109
	linphone_core_enable_log_collection(enable_logs);
110 111 112

	marie = linphone_core_manager_new( "marie_rc");
	// wait a few seconds to generate some traffic
113 114 115 116
	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);
117 118 119 120
	}
	return marie;
}

121 122 123 124 125 126 127 128 129
#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) {
130 131
			fputs(buffer, output);
			memset(buffer, 0, strlen(buffer));
132 133
		}

134
		CU_ASSERT_EQUAL(gzclose(file), Z_OK);
135 136 137 138 139 140 141
		ms_free(newname);

		fseek(output, 0, SEEK_SET);
		return (FILE*)output;
}
#endif

142 143
time_t check_file(LinphoneCoreManager* mgr)  {

Guillaume BIENKOWSKI's avatar
Guillaume BIENKOWSKI committed
144
	time_t last_log = ms_time(NULL);
145 146
	char*    filepath = linphone_core_compress_log_collection(mgr->lc);
	time_t  time_curr = -1;
147
	uint32_t timediff = 0;
148
	FILE *file = NULL;
149

150
	CU_ASSERT_PTR_NOT_NULL(filepath);
151

152 153 154 155
	if (filepath != NULL) {
		int line_count = 0;
		char *line = NULL;
		size_t line_size = 256;
156
#ifndef WIN32
157 158
		struct tm tm_curr;
		time_t time_prev = -1;
159
#endif
160

161 162 163 164 165 166 167
#if HAVE_ZLIB
		// 0) if zlib is enabled, we must decompress the file first
		file = gzuncompress(filepath);
#else
		file = fopen(filepath, "r");
#endif

168 169 170 171 172
		// 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) {
173
			// a) there should be at least 25 lines
174
			++line_count;
175
#ifndef WIN32
176 177 178 179 180 181 182 183 184 185
			// 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;
				}
			}
186 187 188
#else
			ms_warning("strptime() not available for this platform, test is incomplete.");
#endif
189
		}
190
		CU_ASSERT_TRUE(line_count > 25);
191 192 193
		free(line);
		fclose(file);
		ms_free(filepath);
194

195
		timediff = labs((long int)time_curr - (long int)last_log);
196

197 198 199 200
		CU_ASSERT_TRUE( timediff <= 1 );
		if( !(timediff <= 1) ){
			ms_error("time_curr: %ld, last_log: %ld timediff: %d", time_curr, last_log, timediff );
		}
201
	}
202 203 204 205 206 207 208
	// 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));
209
	collect_cleanup(marie);
210 211 212 213
}

static void collect_files_filled() {
	LinphoneCoreManager* marie = setup(TRUE);
214
	check_file(marie);
215
	collect_cleanup(marie);
216 217 218 219
}

static void collect_files_small_size()  {
	LinphoneCoreManager* marie = setup(TRUE);
220
	linphone_core_set_log_collection_max_file_size(5000);
221
	check_file(marie);
222
	collect_cleanup(marie);
223 224 225 226 227 228
}

static void collect_files_changing_size()  {
	LinphoneCoreManager* marie = setup(TRUE);
	int waiting = 100;

229
	check_file(marie);
230

231
	linphone_core_set_log_collection_max_file_size(5000);
232 233 234
	// Generate some logs
	while (--waiting) ms_error("(test error)Waiting %d...", waiting);

235
	check_file(marie);
236

237
	collect_cleanup(marie);
238 239 240 241 242 243
}

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},
244
	{ "Logs collected when decreasing max size", collect_files_changing_size},
245 246 247 248
};

test_suite_t log_collection_test_suite = {
	"LogCollection",
249 250
	NULL,
	NULL,
251 252 253 254
	sizeof(log_collection_tests) / sizeof(log_collection_tests[0]),
	log_collection_tests
};