1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*  Fluent Bit
4  *  ==========
5  *  Copyright (C) 2015-2016 Treasure Data Inc.
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License");
8  *  you may not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS,
15  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  */
19 
20 #include <fluent-bit.h>
21 #include <pthread.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include "flb_tests_runtime.h"
25 
26 
27 int64_t result_time;
set_result(int64_t v)28 static inline int64_t set_result(int64_t v)
29 {
30     int64_t old = __sync_lock_test_and_set(&result_time, v);
31     return old;
32 }
33 
get_result(void)34 static inline int64_t get_result(void)
35 {
36     int64_t old = __sync_fetch_and_add(&result_time, 0);
37 
38     return old;
39 }
40 
time_in_ms()41 static inline int64_t time_in_ms()
42 {
43     int ms;
44     struct timespec s;
45     TEST_CHECK(clock_gettime(CLOCK_MONOTONIC, &s) == 0);
46     ms = s.tv_nsec / 1.0e6;
47     if (ms >= 1000) {
48         ms = 0;
49     }
50     return 1000 * s.tv_sec + ms;
51 }
52 
callback_test(void * data,size_t size,void * cb_data)53 int callback_test(void* data, size_t size, void* cb_data)
54 {
55     if (size > 0) {
56         flb_info("[test] flush triggered");
57         flb_lib_free(data);
58         set_result(time_in_ms()); /* success */
59     }
60     return 0;
61 }
62 
do_test(char * system,...)63 void do_test(char *system, ...)
64 {
65     int64_t ret;
66     flb_ctx_t    *ctx    = NULL;
67     int in_ffd;
68     int out_ffd;
69     va_list va;
70     char *key;
71     char *value;
72 
73     struct flb_lib_out_cb cb;
74     cb.cb   = callback_test;
75     cb.data = NULL;
76 
77     /* initialize */
78     set_result(0);
79 
80     ctx = flb_create();
81 
82     in_ffd = flb_input(ctx, (char *) system, NULL);
83     TEST_CHECK(in_ffd >= 0);
84     TEST_CHECK(flb_input_set(ctx, in_ffd, "tag", "test", NULL) == 0);
85 
86     va_start(va, system);
87     while ((key = va_arg(va, char *))) {
88         value = va_arg(va, char *);
89         TEST_CHECK(value != NULL);
90         TEST_CHECK(flb_input_set(ctx, in_ffd, key, value, NULL) == 0);
91     }
92     va_end(va);
93 
94     out_ffd = flb_output(ctx, (char *) "lib", &cb);
95     TEST_CHECK(out_ffd >= 0);
96     TEST_CHECK(flb_output_set(ctx, out_ffd, "match", "test", NULL) == 0);
97 
98     TEST_CHECK(flb_service_set(ctx, "Flush", "0.5",
99                                     "Grace", "1",
100                                     NULL) == 0);
101 
102     /* The following test tries to check if an input plugin generates
103      * data in a timely manner.
104      *
105      *    0     1     2     3     4   (sec)
106      *    |--F--F--F--C--F--F--F--C--|
107      *
108      *    F ... Flush (0.5 sec interval)
109      *    C ... Condition checks
110      *
111      * Since CI servers can be sometimes very slow, we wait slightly a
112      * little more before checking the condition.
113      */
114 
115     /* Start test */
116     TEST_CHECK(flb_start(ctx) == 0);
117 
118     /* 2 sec passed. It must have flushed */
119     sleep(2);
120     flb_info("[test] check status 1");
121     ret = get_result();
122     TEST_CHECK(ret > 0);
123 
124     /* 4 sec passed. It must have flushed */
125     sleep(2);
126     flb_info("[test] check status 2");
127     ret = get_result();
128     TEST_CHECK(ret > 0);
129 
130     flb_stop(ctx);
131     flb_destroy(ctx);
132 }
133 
flb_test_in_disk_flush()134 void flb_test_in_disk_flush()
135 {
136     do_test("disk",
137             "interval_sec", "0",
138             "interval_nsec", "500000000",
139             NULL);
140 }
flb_test_in_proc_flush()141 void flb_test_in_proc_flush()
142 {
143     do_test("proc",
144             "interval_sec", "0",
145             "interval_nsec", "500000000",
146             "proc_name", "flb_test_in_proc",
147             "alert", "true",
148             "mem", "on",
149             "fd", "on",
150             NULL);
151 }
flb_test_in_head_flush()152 void flb_test_in_head_flush()
153 {
154     do_test("head",
155             "interval_sec", "0",
156             "interval_nsec", "500000000",
157             "File", "/dev/urandom",
158             NULL);
159 }
flb_test_in_cpu_flush()160 void flb_test_in_cpu_flush()
161 {
162     do_test("cpu", NULL);
163 }
flb_test_in_random_flush()164 void flb_test_in_random_flush()
165 {
166     do_test("random", NULL);
167 }
flb_test_in_dummy_flush()168 void flb_test_in_dummy_flush()
169 {
170     do_test("dummy", NULL);
171 }
flb_test_in_mem_flush()172 void flb_test_in_mem_flush()
173 {
174     do_test("mem", NULL);
175 }
176 
177 #ifdef in_proc
flb_test_in_proc_absent_process(void)178 void flb_test_in_proc_absent_process(void)
179 {
180     int ret;
181     flb_ctx_t    *ctx    = NULL;
182     int in_ffd;
183     int out_ffd;
184 
185     struct flb_lib_out_cb cb;
186     cb.cb   = callback_test;
187     cb.data = NULL;
188 
189     ctx = flb_create();
190 
191     in_ffd = flb_input(ctx, (char *) "proc", NULL);
192     TEST_CHECK(in_ffd >= 0);
193     flb_input_set(ctx, in_ffd, "tag", "test",
194                   "interval_sec", "1", "proc_name", "",
195                   "alert", "true", "mem", "on", "fd", "on", NULL);
196 
197     out_ffd = flb_output(ctx, (char *) "lib", &cb);
198     TEST_CHECK(out_ffd >= 0);
199     flb_output_set(ctx, out_ffd, "match", "test", NULL);
200 
201     flb_service_set(ctx, "Flush", "2", "Grace", "1", NULL);
202 
203     ret = flb_start(ctx);
204     TEST_CHECK(ret == 0); // error occurs but return value is true
205 
206     flb_stop(ctx);
207     flb_destroy(ctx);
208 }
209 #endif
210 
211 /* Test list */
212 TEST_LIST = {
213 #ifdef in_disk
214     {"disk_flush",    flb_test_in_disk_flush},
215 #endif
216 #ifdef in_proc
217     {"proc_flush",    flb_test_in_proc_flush},
218     {"proc_absent_process",     flb_test_in_proc_absent_process},
219 #endif
220 #ifdef in_head
221     {"head_flush",    flb_test_in_head_flush},
222 #endif
223 #ifdef in_cpu
224     {"cpu_flush",     flb_test_in_cpu_flush},
225 #endif
226 #ifdef in_random
227     {"random_flush",  flb_test_in_random_flush},
228 #endif
229 #ifdef in_dummy
230     {"dummy_flush",   flb_test_in_dummy_flush},
231 #endif
232 #ifdef in_mem
233     {"mem_flush",     flb_test_in_mem_flush},
234 #endif
235     {NULL, NULL}
236 };
237 
238