GCC Code Coverage Report


Directory: src/gate/
File: src/gate/system/tests/gateservice_test/gateservice_test.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 95 115 82.6%
Functions: 9 13 69.2%
Branches: 26 40 65.0%

Line Branch Exec Source
1 #include "gate/gatemain.h"
2 #include "gate/console.h"
3 #include "gate/results.h"
4 #include "gate/applications.h"
5 #include "gate/strings.h"
6 #include "gate/processes.h"
7 #include "gate/files.h"
8 #include "gate/environments.h"
9 #include "gate/system/services.h"
10 #include "gate/io/logging.h"
11 #include "gate/debugging.h"
12
13 #if defined(GATE_COMPILER_MSVC) && defined(GATE_LEAK_DETECTION) && defined(GATE_SYS_WIN) && !defined(GATE_SYS_WINCE) && (GATE_ARCH != GATE_ARCH_ARM32) && (GATE_ARCH != GATE_ARCH_ARM64)
14 # include <vld.h>
15 #endif
16
17 static gate_string_t const test_service_name = GATE_STRING_INIT_STATIC("gate_test_service");
18 static gate_string_t const test_service_descr = GATE_STRING_INIT_STATIC("GATE Test Service");
19
20
21 typedef struct service_args_class
22 {
23 gate_bool_t register_svc;
24 gate_bool_t unregister_svc;
25 gate_bool_t start;
26 gate_bool_t status;
27 gate_bool_t stop;
28 gate_bool_t help;
29 } service_args_t;
30
31 static service_args_t service_args;
32
33 static gate_app_option_t service_options[] =
34 {
35 GATE_APP_OPTION_INIT_STATIC("register", GATE_APP_OPTION_TYPE_SWITCH, &service_args.register_svc, "R", "service", "Registers the service process"),
36 GATE_APP_OPTION_INIT_STATIC("unregister", GATE_APP_OPTION_TYPE_SWITCH, &service_args.unregister_svc, "U", "service", "Unregisters the service process"),
37 GATE_APP_OPTION_INIT_STATIC("start", GATE_APP_OPTION_TYPE_SWITCH, &service_args.start, "S", "service", "Starts the service"),
38 GATE_APP_OPTION_INIT_STATIC("status", GATE_APP_OPTION_TYPE_SWITCH, &service_args.status, "T", "service", "Shows running status"),
39 GATE_APP_OPTION_INIT_STATIC("stop", GATE_APP_OPTION_TYPE_SWITCH, &service_args.stop, "P", "service", "Stops the service"),
40
41 GATE_APP_OPTION_INIT_STATIC("help", GATE_APP_OPTION_TYPE_SWITCH, &service_args.help, "?", "show_help", "Shows help")
42 };
43
44 1 static gate_result_t svc_init(gate_appservice_t* service, char const* program, char const* const* arguments, gate_size_t argcount, gate_uintptr_t apphandle)
45 {
46 1 gate_logger_t const* logger = gate_logger_get();
47 gate_strbuilder_t msg_builder;
48 gate_size_t ndx;
49
50 GATE_UNUSED_ARG(service);
51 GATE_UNUSED_ARG(apphandle);
52
53 1 gate_strbuilder_create(&msg_builder, 256);
54 1 gate_strbuilder_append(&msg_builder,
55 GATE_PRINT_CSTR, "INIT: ",
56 GATE_PRINT_CSTR, program,
57 GATE_PRINT_END);
58
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for (ndx = 0; ndx != argcount; ++ndx)
59 {
60 gate_strbuilder_append_cstr(&msg_builder, " ");
61 gate_strbuilder_append_cstr(&msg_builder, arguments[ndx]);
62 }
63
64 1 GATE_LOG_INFO(logger, "svc_init", gate_strbuilder_ptr(&msg_builder, 0));
65
66 1 gate_strbuilder_release(&msg_builder);
67 1 return GATE_RESULT_OK;
68 }
69
70 1 static gate_result_t svc_run(gate_appservice_t* service)
71 {
72 1 gate_logger_t const* logger = gate_logger_get();
73
74 GATE_UNUSED_ARG(service);
75 1 GATE_LOG_INFO(logger, "svc_run", "RUN");
76 1 return GATE_RESULT_OK;
77 }
78
79 static gate_result_t svc_on_signal(gate_appservice_t* service, int appsignal)
80 {
81 gate_logger_t const* logger = gate_logger_get();
82
83 GATE_UNUSED_ARG(service);
84 GATE_LOG_FAIL_INFO(logger, appsignal, 0, "svc_on_signal", "SIGNAL");
85 return GATE_RESULT_OK;
86 }
87
88 1 static gate_size_t svc_get_servicename(gate_appservice_t* service, char* buffer, gate_size_t bufferlength)
89 {
90 GATE_UNUSED_ARG(service);
91 1 return gate_str_print_text(buffer, bufferlength, test_service_name.str, test_service_name.length);
92 }
93
94 1 static gate_result_t svc_on_start(gate_appservice_t* service)
95 {
96 1 gate_logger_t const* logger = gate_logger_get();
97
98 GATE_UNUSED_ARG(service);
99 1 GATE_LOG_STATUS(logger, "svc_on_start", "START");
100 1 return GATE_RESULT_OK;
101 }
102 1 static gate_result_t svc_on_stop(gate_appservice_t* service)
103 {
104 1 gate_logger_t const* logger = gate_logger_get();
105
106 GATE_UNUSED_ARG(service);
107 1 GATE_LOG_STATUS(logger, "svc_on_stop", "STOP");
108 1 return GATE_RESULT_OK;
109 }
110 static gate_result_t svc_on_pause(gate_appservice_t* service)
111 {
112 gate_logger_t const* logger = gate_logger_get();
113
114 GATE_UNUSED_ARG(service);
115 GATE_LOG_STATUS(logger, "svc_on_pause", "PAUSE");
116 return GATE_RESULT_OK;
117 }
118 static gate_result_t svc_on_continue(gate_appservice_t* service)
119 {
120 gate_logger_t const* logger = gate_logger_get();
121
122 GATE_UNUSED_ARG(service);
123 GATE_LOG_STATUS(logger, "svc_on_continue", "CONTINUE");
124 return GATE_RESULT_OK;
125 }
126 static gate_result_t svc_on_error(gate_appservice_t* service, gate_result_t resultcode, gate_int32_t nativecode, char const* message)
127 {
128 gate_logger_t const* logger = gate_logger_get();
129
130 GATE_UNUSED_ARG(service);
131 GATE_LOG_FAIL_ERROR(logger, resultcode, nativecode, "svc_on_error", message);
132 return GATE_RESULT_OK;
133 }
134
135 1 static void start_logging(char const* program)
136 {
137 gate_strbuilder_t builder;
138 char file_buffer[GATE_MAX_FILEPATH_LENGTH];
139 1 gate_string_t file_path = GATE_STRING_INIT_EMPTY;
140 1 gate_process_id_t pid = 0;
141
142 1 gate_process_get_id(&pid);
143 1 gate_strbuilder_create_static(&builder, file_buffer, sizeof(file_buffer), 0);
144 1 gate_strbuilder_append_cstr(&builder, program);
145 1 gate_strbuilder_append_cstr(&builder, "_");
146 1 gate_strbuilder_append_int64(&builder, pid);
147 1 gate_strbuilder_append_cstr(&builder, ".log");
148 1 gate_strbuilder_to_string(&builder, &file_path);
149
150 1 gate_logger_start(&file_path, GATE_LOG_TYPE_DEBUG);
151
152 1 gate_string_release(&file_path);
153 1 }
154
155 1 static void stop_logging()
156 {
157 1 gate_logger_stop();
158 1 }
159
160 4 static void service_command_message_callback(gate_string_t const* message, void* user_param)
161 {
162 4 gate_stream_t* strm = gate_console_error_stream();
163 4 gate_stream_print_string(strm, message);
164 4 gate_stream_println_cstr(strm, NULL);
165 4 }
166
167 7 int gate_main(char const* program, char const* const* arguments, gate_size_t argcount, gate_uintptr_t apphandle)
168 {
169 int ret;
170 gate_appservice_t svc;
171 7 gate_result_t result = GATE_RESULT_OK;
172 7 gate_console_t* console = gate_console();
173 7 gate_stream_t* con = (gate_stream_t*)console;
174 7 gate_logger_t const* logger = NULL;
175 7 gate_string_t service_exe = GATE_STRING_INIT_EMPTY;
176 char exebuffer[GATE_MAX_FILEPATH_LENGTH];
177 7 gate_size_t exebufferlen = sizeof(exebuffer) - 1;
178
179 7 gate_env_app_executable_str(exebuffer, &exebufferlen);
180 7 exebuffer[exebufferlen] = 0;
181 7 GATE_DEBUG_TRACE(exebuffer);
182
183 7 gate_string_create_static_len(&service_exe, exebuffer, exebufferlen);
184
185 7 gate_app_options_parse_strs(arguments, argcount, service_options, sizeof(service_options) / sizeof(service_options[0]));
186
187
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6 times.
7 if (service_args.register_svc)
188 {
189 1 result = gate_service_register(&test_service_name, &service_exe, &test_service_descr, 0, NULL, NULL, NULL);
190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(result, "gate_service_register() failed");
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 return GATE_RESULT_TO_EXITCODE(result);
192 }
193
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5 times.
6 else if (service_args.unregister_svc)
194 {
195 1 result = gate_service_unregister(&test_service_name, NULL, NULL);
196
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(result, "gate_service_unregister() failed");
197
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 return GATE_RESULT_TO_EXITCODE(result);
198 }
199
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 else if (service_args.start)
200 {
201 1 result = gate_service_start(&test_service_name, &service_command_message_callback, NULL);
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(result, "gate_service_start() failed");
203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 return GATE_RESULT_TO_EXITCODE(result);
204 }
205
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 else if (service_args.status)
206 {
207 1 gate_enumint_t status = 0;
208 1 gate_string_t process_id = GATE_STRING_INIT_EMPTY;
209 1 result = gate_service_get_status(&test_service_name, &status, &process_id);
210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(result, "gate_service_get_status() failed");
211
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(result))
212 {
213 1 gate_stream_print_cstr(con, "Service state: ");
214 1 gate_stream_print_cstr(con, gate_service_print_state(status));
215
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!gate_string_is_empty(&process_id))
216 {
217 gate_stream_print_cstr(con, ", PID=");
218 gate_stream_print_string(con, &process_id);
219 }
220 1 gate_stream_println_cstr(con, NULL);
221 1 gate_string_release(&process_id);
222 }
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 return GATE_RESULT_TO_EXITCODE(result);
224 }
225
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 else if (service_args.stop)
226 {
227 1 result = gate_service_stop(&test_service_name, 0, false, &service_command_message_callback, NULL);
228
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(result, "gate_service_start() failed");
229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 return GATE_RESULT_TO_EXITCODE(result);
230 }
231
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 else if (service_args.help)
232 {
233 1 gate_app_options_print(service_options, sizeof(service_options) / sizeof(service_options[0]), con);
234 1 return 0;
235 }
236
237
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 start_logging(exebufferlen ? &exebuffer[0] : program);
238 1 logger = gate_logger_get();
239
240 1 GATE_LOG_DEBUG(logger, "main", "service_init()");
241
242 1 gate_appservice_init(&svc, &svc_init, &svc_run, &svc_on_signal, &svc_get_servicename,
243 &svc_on_start, &svc_on_stop, &svc_on_pause, &svc_on_continue, &svc_on_error);
244
245 1 GATE_LOG_DEBUG(logger, "main", "service_run");
246 1 ret = gate_appservice_run(&svc, program, arguments, argcount, apphandle);
247 1 GATE_LOG_DEBUG(logger, "main", "service_run exit");
248 1 stop_logging();
249 1 return ret;
250 }
251