1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 * Copyright (C) 2021 Frediano Ziglio
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20 /*
21 * Check log elision implementation
22 */
23 #include "common.h"
24 #include <assert.h>
25 #include <freetds/utils.h>
26
27 #if HAVE_UNISTD_H
28 #undef getpid
29 #include <unistd.h>
30 #endif /* HAVE_UNISTD_H */
31
32 enum {
33 LOOP = 100,
34 THREADS = 3,
35 };
36
TDS_THREAD_PROC_DECLARE(log_func,idx_ptr)37 static TDS_THREAD_PROC_DECLARE(log_func, idx_ptr)
38 {
39 const int idx = TDS_PTR2INT(idx_ptr);
40 const char letter = 'A' + idx;
41 TDSDUMP_OFF_ITEM off_item;
42 int n = idx, i;
43
44 /* LOOP times */
45 for (i = 0; i < LOOP; ++i) {
46 /* send log */
47 tdsdump_log(TDS_DBG_ERROR, "Some log from %c number %d\n", letter, n);
48
49 /* wait 1-10 ms */
50 tds_sleep_ms((rand() % 10) + 1);
51
52 /* disable logs */
53 tdsdump_off(&off_item);
54
55 /* send wrong log */
56 tdsdump_log(TDS_DBG_ERROR, "Disabled log %c number %d\n", letter, n);
57
58 /* wait 1-10 ms */
59 tds_sleep_ms((rand() % 10) + 1);
60
61 /* enable logs */
62 tdsdump_on(&off_item);
63
64 n += 3;
65 }
66
67 return TDS_THREAD_RESULT(0);
68 }
69
70 int
main(int argc,char ** argv)71 main(int argc, char **argv)
72 {
73 int i, ret;
74 tds_thread threads[THREADS];
75 FILE *f;
76 char line[1024];
77 int wrong_lines = 0;
78 int nexts[THREADS];
79
80 tds_debug_flags = TDS_DBGFLAG_ALL | TDS_DBGFLAG_SOURCE;
81
82 /* remove file */
83 unlink("log_elision.out");
84
85 /* set output file */
86 tdsdump_open("log_elision.out");
87
88 /* THREADS thread */
89 for (i = 0; i < THREADS; ++i) {
90 nexts[i] = i;
91 }
92 for (i = 1; i < THREADS; ++i) {
93 ret = tds_thread_create(&threads[i], log_func, TDS_INT2PTR(i));
94 assert(ret == 0);
95 }
96 log_func(TDS_INT2PTR(0));
97 for (i = 1; i < THREADS; ++i) {
98 ret = tds_thread_join(threads[i], NULL);
99 assert(ret == 0);
100 }
101
102 /* close logs */
103 tdsdump_close();
104
105 /* open logs to read */
106 f = fopen("log_elision.out", "r");
107 assert(f != NULL);
108
109 /* read line by line */
110 while (fgets(line, sizeof(line), f) != NULL) {
111 char thread_letter;
112 int num_line, num, idx;
113
114 /* ignore some start lines */
115 if (strstr(line, "log_elision.c") == NULL) {
116 assert(++wrong_lines < 4);
117 continue;
118 }
119
120 ret = sscanf(line, "log_elision.c:%d:Some log from %c number %d\n",
121 &num_line, &thread_letter, &num);
122 assert(ret == 3);
123
124 /* detect number of thread */
125 assert(thread_letter >= 'A' && thread_letter < 'A' + THREADS);
126 idx = thread_letter - 'A';
127
128 /* check number inside string match the next */
129 assert(num == nexts[idx]);
130 nexts[idx] += 3;
131 }
132 fclose(f);
133 f = NULL;
134
135 /* check we got all numbers */
136 for (i = 0; i < THREADS; ++i) {
137 assert(nexts[i] == i + LOOP * 3);
138 }
139
140 /* cleanup file */
141 unlink("log_elision.out");
142
143 return 0;
144 }
145