Line data Source code
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 : #ifdef TDS_HAVE_MUTEX
33 : enum {
34 : LOOP = 100,
35 : THREADS = 3,
36 : };
37 :
38 30 : static TDS_THREAD_PROC_DECLARE(log_func, idx_ptr)
39 : {
40 30 : const int idx = TDS_PTR2INT(idx_ptr);
41 30 : const char letter = 'A' + idx;
42 : TDSDUMP_OFF_ITEM off_item;
43 30 : int n = idx, i;
44 :
45 : /* LOOP times */
46 3030 : for (i = 0; i < LOOP; ++i) {
47 : /* send log */
48 3000 : tdsdump_log(TDS_DBG_ERROR, "Some log from %c number %d\n", letter, n);
49 :
50 : /* wait 1-10 ms */
51 3000 : tds_sleep_ms((rand() % 10) + 1);
52 :
53 : /* disable logs */
54 3000 : tdsdump_off(&off_item);
55 :
56 : /* send wrong log */
57 3000 : tdsdump_log(TDS_DBG_ERROR, "Disabled log %c number %d\n", letter, n);
58 :
59 : /* wait 1-10 ms */
60 3000 : tds_sleep_ms((rand() % 10) + 1);
61 :
62 : /* enable logs */
63 3000 : tdsdump_on(&off_item);
64 :
65 3000 : n += 3;
66 : }
67 :
68 30 : return TDS_THREAD_RESULT(0);
69 : }
70 :
71 10 : TEST_MAIN()
72 : {
73 : int i, ret;
74 : tds_thread threads[THREADS];
75 : FILE *f;
76 : char line[1024];
77 10 : int wrong_lines = 0;
78 : int nexts[THREADS];
79 :
80 10 : tds_debug_flags = TDS_DBGFLAG_ALL | TDS_DBGFLAG_SOURCE;
81 :
82 : /* remove file */
83 10 : unlink("log_elision.out");
84 :
85 : /* set output file */
86 10 : tdsdump_open(TDS_DIR("log_elision.out"));
87 :
88 : /* THREADS thread */
89 40 : for (i = 0; i < THREADS; ++i) {
90 30 : nexts[i] = i;
91 : }
92 20 : for (i = 1; i < THREADS; ++i) {
93 40 : ret = tds_thread_create(&threads[i], log_func, TDS_INT2PTR(i));
94 20 : assert(ret == 0);
95 : }
96 10 : log_func(TDS_INT2PTR(0));
97 30 : for (i = 1; i < THREADS; ++i) {
98 40 : ret = tds_thread_join(threads[i], NULL);
99 20 : assert(ret == 0);
100 : }
101 :
102 : /* close logs */
103 10 : tdsdump_close();
104 :
105 : /* open logs to read */
106 10 : f = fopen("log_elision.out", "r");
107 10 : assert(f != NULL);
108 :
109 : /* read line by line */
110 3030 : while (fgets(line, sizeof(line), f) != NULL) {
111 : char thread_letter;
112 : int num, idx;
113 : char *start;
114 :
115 : /* ignore some start lines */
116 3020 : if (strstr(line, "log_elision.c") == NULL) {
117 20 : assert(++wrong_lines < 4);
118 20 : continue;
119 : }
120 :
121 3000 : start = strstr(line, ":Some log from");
122 3000 : assert(start != NULL);
123 :
124 3000 : ret = sscanf(start, ":Some log from %c number %d\n",
125 : &thread_letter, &num);
126 3000 : assert(ret == 2);
127 :
128 : /* detect number of thread */
129 3000 : assert(thread_letter >= 'A' && thread_letter < 'A' + THREADS);
130 3000 : idx = thread_letter - 'A';
131 :
132 : /* check number inside string match the next */
133 3000 : assert(num == nexts[idx]);
134 3000 : nexts[idx] += 3;
135 : }
136 10 : fclose(f);
137 10 : f = NULL;
138 :
139 : /* check we got all numbers */
140 40 : for (i = 0; i < THREADS; ++i) {
141 30 : assert(nexts[i] == i + LOOP * 3);
142 : }
143 :
144 : /* cleanup file */
145 10 : unlink("log_elision.out");
146 :
147 10 : return 0;
148 : }
149 : #else /* !TDS_HAVE_MUTEX */
150 : TEST_MAIN()
151 : {
152 : printf("Not possible for this platform.\n");
153 : return 0; /* TODO 77 ? */
154 : }
155 : #endif
|