Branch data Line data Source code
1 : : #include "sute.h"
2 : :
3 : : /**
4 : : * Run background scenario with SIGTERM and verify output template.
5 : : */
6 : 2 : static Return test0033_1(void)
7 : : {
8 : 2 : INITTEST;
9 : :
10 : 2 : const char *arguments = "--progress --database=0033_interrupt_resume.db tests/fixtures/diffs/";
11 : 2 : const char *filename = "templates/0033_001.txt";
12 : 2 : const char *cleanup_path = "0033_interrupt_resume.db";
13 : :
14 : 2 : create(char,stdout_result);
15 : 2 : create(char,stderr_result);
16 : 2 : create(char,stdout_pattern);
17 : 2 : create(char,stderr_pattern);
18 : :
19 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
20 : :
21 : 2 : ASSERT(SUCCESS == runit_background(
22 : : arguments,
23 : : stdout_result,
24 : : stderr_result,
25 : : SUCCESS|HALTED,
26 : : ALLOW_BOTH,
27 : : 500U,
28 : : 5000U,
29 : : SIGTERM,
30 : : 1U));
31 : :
32 : 2 : ASSERT(SUCCESS == get_file_content(filename,stdout_pattern));
33 : 2 : ASSERT(SUCCESS == match_pattern(stdout_result,stdout_pattern,filename));
34 : :
35 : 2 : ASSERT(SUCCESS == copy_literal(stderr_pattern,"\\A\\Z"));
36 : 2 : ASSERT(SUCCESS == match_pattern(stderr_result,stderr_pattern));
37 : :
38 : 2 : ASSERT(SUCCESS == delete_path(cleanup_path));
39 : :
40 : 2 : del(stderr_pattern);
41 : 2 : del(stdout_pattern);
42 : 2 : del(stderr_result);
43 : 2 : del(stdout_result);
44 : :
45 : 2 : RETURN_STATUS;
46 : : }
47 : :
48 : : /**
49 : : * Run background scenario with SIGINT and verify output template.
50 : : */
51 : 2 : static Return test0033_2(void)
52 : : {
53 : 2 : INITTEST;
54 : :
55 : 2 : const char *arguments = "--progress --database=0033_interrupt_resume.db tests/fixtures/diffs/";
56 : 2 : const char *filename = "templates/0033_002.txt";
57 : 2 : const char *cleanup_path = "0033_interrupt_resume.db";
58 : :
59 : 2 : create(char,stdout_result);
60 : 2 : create(char,stderr_result);
61 : 2 : create(char,stdout_pattern);
62 : 2 : create(char,stderr_pattern);
63 : :
64 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
65 : :
66 : 2 : ASSERT(SUCCESS == runit_background(
67 : : arguments,
68 : : stdout_result,
69 : : stderr_result,
70 : : SUCCESS|HALTED,
71 : : ALLOW_BOTH,
72 : : 500U,
73 : : 5000U,
74 : : SIGINT,
75 : : 1U));
76 : :
77 : 2 : ASSERT(SUCCESS == get_file_content(filename,stdout_pattern));
78 : 2 : ASSERT(SUCCESS == match_pattern(stdout_result,stdout_pattern,filename));
79 : :
80 : 2 : ASSERT(SUCCESS == copy_literal(stderr_pattern,"\\A\\Z"));
81 : 2 : ASSERT(SUCCESS == match_pattern(stderr_result,stderr_pattern));
82 : :
83 : 2 : ASSERT(SUCCESS == delete_path(cleanup_path));
84 : :
85 : 2 : del(stderr_pattern);
86 : 2 : del(stdout_pattern);
87 : 2 : del(stderr_result);
88 : 2 : del(stdout_result);
89 : :
90 : 2 : RETURN_STATUS;
91 : : }
92 : :
93 : : /**
94 : : * Interrupt hashing of hugetestfile, resume with --update, and verify SHA512.
95 : : */
96 : 2 : static Return test0033_3(void)
97 : : {
98 : 2 : INITTEST;
99 : :
100 : 2 : const char *relative_path = "hugetestfile";
101 : 2 : const char *first_run_template = "templates/0033_003_1.txt";
102 : 2 : const char *second_run_template = "templates/0033_003_2.txt";
103 : :
104 : 2 : create(char,stdout_result);
105 : 2 : create(char,stderr_result);
106 : 2 : create(char,stdout_pattern);
107 : 2 : create(char,stderr_pattern);
108 : 2 : create(char,huge_file_path);
109 : :
110 : : /*
111 : : * Step 1: Prepare isolated test data in TMPDIR and start from a clean DB
112 : : */
113 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
114 : 2 : ASSERT(SUCCESS == create_directory("tests/fixtures"));
115 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/fixtures/huge","tests/fixtures/huge",REQUIRE_SOURCE_EXISTS));
116 : :
117 : 2 : ASSERT(SUCCESS == construct_path("tests/fixtures/huge/hugetestfile",huge_file_path));
118 : :
119 : : /*
120 : : * Read the real file size from the filesystem once and use it as
121 : : * an upper bound for the interrupted offset assertions below
122 : : */
123 : 2 : struct stat huge_file_stat = {0};
124 : 2 : ASSERT(0 == stat(getcstring(huge_file_path),&huge_file_stat));
125 : 2 : ASSERT(huge_file_stat.st_size > 0);
126 : :
127 : 2 : const char *arguments = "--progress --database=0033_interrupt_resume.db tests/fixtures/huge";
128 : :
129 : : /*
130 : : * Step 2: Run in background, wait until hashing reaches wait-point 2,
131 : : * then deliver SIGINT. The process must exit as SUCCESS|HALTED
132 : : */
133 : 2 : ASSERT(SUCCESS == runit_background(
134 : : arguments,
135 : : stdout_result,
136 : : stderr_result,
137 : : SUCCESS|HALTED,
138 : : ALLOW_BOTH,
139 : : 500U,
140 : : 5000U,
141 : : SIGINT,
142 : : 2U));
143 : :
144 : : /*
145 : : * Step 3: Validate first-run output.
146 : : * It must contain the interruption scenario messages and no stderr output
147 : : */
148 : 2 : ASSERT(SUCCESS == get_file_content(first_run_template,stdout_pattern));
149 : 2 : ASSERT(SUCCESS == match_pattern(stdout_result,stdout_pattern,first_run_template));
150 : :
151 : 2 : ASSERT(SUCCESS == copy_literal(stderr_pattern,"\\A\\Z"));
152 : 2 : ASSERT(SUCCESS == match_pattern(stderr_result,stderr_pattern));
153 : :
154 : 2 : sqlite3_int64 interrupted_offset = 0;
155 : 2 : int interrupted_md_context_bytes = 0;
156 : :
157 : : /*
158 : : * Step 4: Read intermediate resume state from DB.
159 : : * The interrupted offset must be inside (0, real_file_size),
160 : : * and mdContext blob must be non-empty for resume.
161 : : */
162 : 2 : ASSERT(SUCCESS == read_resume_state_from_db("0033_interrupt_resume.db",relative_path,&interrupted_offset,&interrupted_md_context_bytes));
163 : :
164 : 2 : ASSERT(interrupted_offset > 0);
165 : 2 : ASSERT(interrupted_offset < (sqlite3_int64)huge_file_stat.st_size);
166 : :
167 : 2 : ASSERT(interrupted_md_context_bytes > 0);
168 : :
169 : : /*
170 : : * Step 5: Resume hashing with --update and verify second-run output
171 : : */
172 : 2 : arguments = "--update --progress --database=0033_interrupt_resume.db tests/fixtures/huge";
173 : 2 : ASSERT(SUCCESS == runit(arguments,stdout_result,stderr_result,COMPLETED,ALLOW_BOTH));
174 : :
175 : 2 : ASSERT(SUCCESS == get_file_content(second_run_template,stdout_pattern));
176 : 2 : ASSERT(SUCCESS == match_pattern(stdout_result,stdout_pattern,second_run_template));
177 : :
178 : 2 : ASSERT(SUCCESS == copy_literal(stderr_pattern,"\\A\\Z"));
179 : 2 : ASSERT(SUCCESS == match_pattern(stderr_result,stderr_pattern));
180 : :
181 : 2 : sqlite3_int64 final_offset = -1;
182 : 2 : unsigned char db_sha512[SHA512_DIGEST_LENGTH] = {0};
183 : 2 : unsigned char expected_sha512[SHA512_DIGEST_LENGTH] = {0};
184 : :
185 : : /*
186 : : * Step 6: Verify final DB state after resume.
187 : : * Offset must be reset to 0 and the stored SHA512 must match file content
188 : : */
189 : 2 : ASSERT(SUCCESS == read_final_sha512_from_db("0033_interrupt_resume.db",relative_path,&final_offset,db_sha512));
190 : :
191 : 2 : ASSERT(0 == final_offset);
192 : :
193 : 2 : ASSERT(SUCCESS == compute_file_sha512(getcstring(huge_file_path),expected_sha512));
194 : 2 : ASSERT(0 == memcmp(db_sha512,expected_sha512,(size_t)SHA512_DIGEST_LENGTH));
195 : :
196 : : /* Step 7: Cleanup temporary test artifacts */
197 : 2 : ASSERT(SUCCESS == delete_path("0033_interrupt_resume.db"));
198 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/huge"));
199 : :
200 : 2 : del(huge_file_path);
201 : 2 : del(stderr_pattern);
202 : 2 : del(stdout_pattern);
203 : 2 : del(stderr_result);
204 : 2 : del(stdout_result);
205 : :
206 : 2 : RETURN_STATUS;
207 : : }
208 : :
209 : : /**
210 : : * Interrupt hashing, modify file metadata, and verify restart from beginning
211 : : */
212 : 2 : static Return test0033_4(void)
213 : : {
214 : 2 : INITTEST;
215 : :
216 : 2 : const char *db_filename = "0033_interrupt_rehash.db";
217 : 2 : const char *relative_path = "hugetestfile";
218 : 2 : const char *first_run_template = "templates/0033_004_1.txt";
219 : 2 : const char *second_run_template = "templates/0033_004_2.txt";
220 : :
221 : 2 : create(char,stdout_result);
222 : 2 : create(char,stderr_result);
223 : 2 : create(char,stdout_pattern);
224 : 2 : create(char,stderr_pattern);
225 : 2 : create(char,huge_file_path);
226 : :
227 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
228 : 2 : ASSERT(SUCCESS == create_directory("tests/fixtures"));
229 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/fixtures/huge","tests/fixtures/huge",REQUIRE_SOURCE_EXISTS));
230 : 2 : ASSERT(SUCCESS == construct_path("tests/fixtures/huge/hugetestfile",huge_file_path));
231 : :
232 : 2 : const char *arguments = "--progress --database=0033_interrupt_rehash.db tests/fixtures/huge";
233 : :
234 : 2 : ASSERT(SUCCESS == runit_background(
235 : : arguments,
236 : : stdout_result,
237 : : stderr_result,
238 : : SUCCESS|HALTED,
239 : : ALLOW_BOTH,
240 : : 500U,
241 : : 5000U,
242 : : SIGINT,
243 : : 2U));
244 : :
245 : 2 : ASSERT(SUCCESS == get_file_content(first_run_template,stdout_pattern));
246 : 2 : ASSERT(SUCCESS == match_pattern(stdout_result,stdout_pattern,first_run_template));
247 : 2 : ASSERT(SUCCESS == copy_literal(stderr_pattern,"\\A\\Z"));
248 : 2 : ASSERT(SUCCESS == match_pattern(stderr_result,stderr_pattern));
249 : :
250 : 2 : sqlite3_int64 interrupted_offset = 0;
251 : 2 : int interrupted_md_context_bytes = 0;
252 : :
253 : 2 : ASSERT(SUCCESS == read_resume_state_from_db(db_filename,relative_path,&interrupted_offset,&interrupted_md_context_bytes));
254 : 2 : ASSERT(interrupted_offset > 0);
255 : 2 : ASSERT(interrupted_md_context_bytes > 0);
256 : :
257 : 2 : ASSERT(SUCCESS == append_byte_to_file(huge_file_path,(unsigned char)'X'));
258 : :
259 : 2 : arguments = "--update --progress --database=0033_interrupt_rehash.db tests/fixtures/huge";
260 : 2 : ASSERT(SUCCESS == runit(arguments,stdout_result,stderr_result,COMPLETED,ALLOW_BOTH));
261 : :
262 : 2 : ASSERT(SUCCESS == get_file_content(second_run_template,stdout_pattern));
263 : 2 : ASSERT(SUCCESS == match_pattern(stdout_result,stdout_pattern,second_run_template));
264 : 2 : ASSERT(SUCCESS == copy_literal(stderr_pattern,"\\A\\Z"));
265 : 2 : ASSERT(SUCCESS == match_pattern(stderr_result,stderr_pattern));
266 : :
267 : 2 : const char *expected_paths[] =
268 : : {
269 : : "hugetestfile"
270 : : };
271 : :
272 : 2 : ASSERT(SUCCESS == db_paths_match(db_filename,expected_paths,(int)(sizeof(expected_paths) / sizeof(expected_paths[0]))));
273 : 2 : ASSERT(SUCCESS == delete_path("0033_interrupt_rehash.db"));
274 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/huge"));
275 : :
276 : 2 : del(huge_file_path);
277 : 2 : del(stderr_pattern);
278 : 2 : del(stdout_pattern);
279 : 2 : del(stderr_result);
280 : 2 : del(stdout_result);
281 : :
282 : 2 : RETURN_STATUS;
283 : : }
284 : :
285 : : /**
286 : : * Background interruption tests grouped as a separate suite.
287 : : */
288 : 2 : Return test0033(void)
289 : : {
290 : 2 : INITTEST;
291 : :
292 : 2 : TEST(test0033_1,"Background run receives SIGTERM and exits with HALTED…");
293 : 2 : TEST(test0033_2,"Background run receives SIGINT and exits with HALTED…");
294 : 2 : TEST(test0033_3,"Random interruption on hugetestfile with resume and SHA512 verification…");
295 : 2 : TEST(test0033_4,"Interrupted hash with file change restarts rehash from the beginning…");
296 : :
297 : 2 : RETURN_STATUS;
298 : : }
|