source: mainline/uspace/lib/pcut/src/os/helenos.c@ 08e103d4

Last change on this file since 08e103d4 was 08e103d4, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Use clearer naming for string length functions

This and the following commit change the names of functions, as well as
their documentation, to use unambiguous terms "bytes" and "code points"
instead of ambiguous terms "size", "length", and "characters".

  • Property mode set to 100644
File size: 6.5 KB
Line 
1/*
2 * Copyright (c) 2013 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file
30 *
31 * Implementation of platform-dependent functions for HelenOS.
32 */
33
34#include <stdlib.h>
35#include <str.h>
36#include <str_error.h>
37#include <errno.h>
38#include <assert.h>
39#include <stdio.h>
40#include <task.h>
41#include <fibril_synch.h>
42#include <vfs/vfs.h>
43#include "../internal.h"
44
45
46/* String functions. */
47
48int pcut_str_equals(const char *a, const char *b) {
49 return str_cmp(a, b) == 0;
50}
51
52
53int pcut_str_start_equals(const char *a, const char *b, int len) {
54 return str_lcmp(a, b, len) == 0;
55}
56
57int pcut_str_bytes(const char *s) {
58 return str_bytes(s);
59}
60
61int pcut_str_to_int(const char *s) {
62 int result = strtol(s, NULL, 10);
63 return result;
64}
65
66char *pcut_str_find_char(const char *haystack, const char needle) {
67 return str_chr(haystack, needle);
68}
69
70void pcut_str_error(int error, char *buffer, int size) {
71 const char *str = str_error(error);
72 if (str == NULL) {
73 str = "(strerror failure)";
74 }
75 str_cpy(buffer, size, str);
76}
77
78
79/* Forking-mode related functions. */
80
81/** Maximum width of a test number. */
82#define MAX_TEST_NUMBER_WIDTH 24
83
84/** Maximum length of a temporary file name. */
85#define PCUT_TEMP_FILENAME_BUFFER_SIZE 128
86
87/** Maximum command-line length. */
88#define MAX_COMMAND_LINE_LENGTH 1024
89
90/** Maximum size of stdout we are able to capture. */
91#define OUTPUT_BUFFER_SIZE 8192
92
93/** Buffer for assertion and other error messages. */
94static char error_message_buffer[OUTPUT_BUFFER_SIZE];
95
96/** Buffer for stdout from the test. */
97static char extra_output_buffer[OUTPUT_BUFFER_SIZE];
98
99/** Prepare for a new test.
100 *
101 * @param test Test that is about to be run.
102 */
103static void before_test_start(pcut_item_t *test) {
104 pcut_report_test_start(test);
105
106 memset(error_message_buffer, 0, OUTPUT_BUFFER_SIZE);
107 memset(extra_output_buffer, 0, OUTPUT_BUFFER_SIZE);
108}
109
110/** Mutex guard for forced_termination_cv. */
111static FIBRIL_MUTEX_INITIALIZE(forced_termination_mutex);
112
113/** Condition-variable for checking whether test timed-out. */
114static FIBRIL_CONDVAR_INITIALIZE(forced_termination_cv);
115
116/** Spawned task id. */
117static task_id_t test_task_id;
118
119/** Flag whether test is still running.
120 *
121 * This flag is used when checking whether test timed-out.
122 */
123static int test_running;
124
125/** Main fibril for checking whether test timed-out.
126 *
127 * @param arg Test that is currently running (pcut_item_t *).
128 * @return EOK Always.
129 */
130static int test_timeout_handler_fibril(void *arg) {
131 pcut_item_t *test = arg;
132 int timeout_sec = pcut_get_test_timeout(test);
133 usec_t timeout_us = SEC2USEC(timeout_sec);
134
135 fibril_mutex_lock(&forced_termination_mutex);
136 if (!test_running) {
137 goto leave_no_kill;
138 }
139 errno_t rc = fibril_condvar_wait_timeout(&forced_termination_cv,
140 &forced_termination_mutex, timeout_us);
141 if (rc == ETIMEOUT) {
142 task_kill(test_task_id);
143 }
144leave_no_kill:
145 fibril_mutex_unlock(&forced_termination_mutex);
146 return EOK;
147}
148
149/** Run the test as a new task and report the result.
150 *
151 * @param self_path Path to itself, that is to current binary.
152 * @param test Test to be run.
153 */
154int pcut_run_test_forking(const char *self_path, pcut_item_t *test) {
155 before_test_start(test);
156
157 char tempfile_name[PCUT_TEMP_FILENAME_BUFFER_SIZE];
158 snprintf(tempfile_name, PCUT_TEMP_FILENAME_BUFFER_SIZE - 1, "pcut_%lld.tmp", (unsigned long long) task_get_id());
159 int tempfile;
160 errno_t rc = vfs_lookup_open(tempfile_name, WALK_REGULAR | WALK_MAY_CREATE, MODE_READ | MODE_WRITE, &tempfile);
161 if (rc != EOK) {
162 pcut_report_test_done(test, PCUT_OUTCOME_INTERNAL_ERROR, "Failed to create temporary file.", NULL, NULL);
163 return PCUT_OUTCOME_INTERNAL_ERROR;
164 }
165
166 char test_number_argument[MAX_TEST_NUMBER_WIDTH];
167 snprintf(test_number_argument, MAX_TEST_NUMBER_WIDTH, "-t%d", test->id);
168
169 const char *const arguments[3] = {
170 self_path,
171 test_number_argument,
172 NULL
173 };
174
175 int status = PCUT_OUTCOME_PASS;
176
177 task_wait_t test_task_wait;
178 rc = task_spawnvf(&test_task_id, &test_task_wait, self_path, arguments,
179 fileno(stdin), tempfile, tempfile);
180 if (rc != EOK) {
181 status = PCUT_OUTCOME_INTERNAL_ERROR;
182 goto leave_close_tempfile;
183 }
184
185 test_running = 1;
186
187 fid_t killer_fibril = fibril_create(test_timeout_handler_fibril, test);
188 if (killer_fibril == 0) {
189 /* FIXME: somehow announce this problem. */
190 task_kill(test_task_id);
191 } else {
192 fibril_add_ready(killer_fibril);
193 }
194
195 task_exit_t task_exit;
196 int task_retval;
197 rc = task_wait(&test_task_wait, &task_exit, &task_retval);
198 if (rc != EOK) {
199 status = PCUT_OUTCOME_INTERNAL_ERROR;
200 goto leave_close_tempfile;
201 }
202 if (task_exit == TASK_EXIT_UNEXPECTED) {
203 status = PCUT_OUTCOME_INTERNAL_ERROR;
204 } else {
205 status = task_retval == 0 ? PCUT_OUTCOME_PASS : PCUT_OUTCOME_FAIL;
206 }
207
208 fibril_mutex_lock(&forced_termination_mutex);
209 test_running = 0;
210 fibril_condvar_signal(&forced_termination_cv);
211 fibril_mutex_unlock(&forced_termination_mutex);
212
213 aoff64_t pos = 0;
214 size_t nread;
215 vfs_read(tempfile, &pos, extra_output_buffer, OUTPUT_BUFFER_SIZE, &nread);
216
217leave_close_tempfile:
218 vfs_put(tempfile);
219 vfs_unlink_path(tempfile_name);
220
221 pcut_report_test_done_unparsed(test, status, extra_output_buffer, OUTPUT_BUFFER_SIZE);
222
223 return status;
224}
225
226void pcut_hook_before_test(pcut_item_t *test) {
227 PCUT_UNUSED(test);
228
229 /* Do nothing. */
230}
Note: See TracBrowser for help on using the repository browser.