1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 /**
28 * Unit tests for KAppendFile
29 */
30 #include <cstring>
31 #include <ktst/unit_test.hpp>
32
33 #include <kfs/impl.h>
34 #include <kfs/appendfile.h>
35
36 #include <klib/out.h>
37 #include <kapp/args.h>
38 #include <kfg/config.h>
39
40 using namespace std;
41
42 TEST_SUITE(AppendFileTestSuite);
43
44 static const char * StringOne = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
45 static const char * FileName = "JoJoBa.Ba";
46
47 static
48 rc_t
checkWriteFile(KFile * File,size_t Pos,size_t Size)49 checkWriteFile ( KFile * File, size_t Pos, size_t Size )
50 {
51 rc_t RCt;
52 size_t NumWrit;
53 size_t StrLen;
54 size_t Offset;
55 size_t ToWr;
56
57 RCt = 0;
58 NumWrit = 0;
59 StrLen = strlen ( StringOne );
60 Offset = 0;
61 ToWr = 0;
62
63 printf ( "[WRI] [%lu]@[%lu]\n", Size, Pos );
64
65 while ( Offset < Size ) {
66 ToWr = Size - Offset;
67 if ( StrLen < ToWr ) {
68 ToWr = StrLen;
69 }
70
71 RCt = KFileWrite (
72 File,
73 Offset + Pos,
74 StringOne,
75 ToWr,
76 & NumWrit
77 );
78 if ( RCt != 0 ) {
79 break;
80 }
81
82 Offset += ToWr;
83 }
84
85 return RCt;
86 } /* checkWriteFile () */
87
88 static
89 rc_t
checkReadFile(KFile * File,size_t Pos,size_t Size)90 checkReadFile ( KFile * File, size_t Pos, size_t Size )
91 {
92 rc_t RCt;
93 size_t NumRead;
94 size_t StrLen;
95 size_t Offset;
96 char * Buf;
97
98 RCt = 0;
99 NumRead = 0;
100 StrLen = strlen ( StringOne );
101 Offset = 0;
102 Buf = NULL;
103
104 printf ( "[REA] [%lu]@[%lu]\n", Size, Pos );
105
106 Buf = (char *) calloc ( Size, sizeof ( char ) );
107 if ( Buf == NULL ) {
108 return 22;
109 }
110
111 RCt = KFileReadAll (
112 File,
113 Pos,
114 Buf,
115 Size,
116 & NumRead
117 );
118 if ( RCt == 0 ) {
119 /* Checking read result */
120 for ( Offset = 0; Offset < Size; Offset ++ ) {
121 if ( Buf [ Offset ] != StringOne [ ( Pos + Offset ) % StrLen ] ) {
122 RCt = 33;
123 break;
124 }
125 }
126 }
127
128 free ( Buf );
129
130 return RCt;
131 } /* checkReadFile () */
132
133 static
134 rc_t
checkMakeFile(const char * Name,size_t Size)135 checkMakeFile ( const char * Name, size_t Size )
136 {
137 rc_t RCt;
138 struct KDirectory * Dir;
139 struct KFile * File;
140
141 RCt = 0;
142 Dir = NULL;
143 File = NULL;
144
145 printf ( "[CRE] [%s] SZ[%lu]\n", FileName, Size );
146
147 RCt = KDirectoryNativeDir ( & Dir );
148 if ( RCt == 0 ) {
149 RCt = KDirectoryCreateFile (
150 Dir,
151 & File,
152 true,
153 0664,
154 kcmInit,
155 "%s",
156 Name
157 );
158 if ( RCt == 0 ) {
159 if ( Size != 0 ) {
160 checkWriteFile ( File, 0, Size );
161 }
162
163 KFileRelease ( File );
164 }
165
166 KDirectoryRelease ( Dir );
167 }
168 return RCt;
169 } /* checkMakeFile () */
170
171 static
172 rc_t
checkOpenFile(KFile ** File,const char * Name,bool Write)173 checkOpenFile ( KFile ** File, const char * Name, bool Write )
174 {
175 rc_t RCt;
176 struct KDirectory * Dir;
177
178 RCt = 0;
179 Dir = NULL;
180
181 printf ( "[OPE] [%s] [%s]\n", FileName, ( Write ? "WR" : "RD" ) );
182
183 RCt = KDirectoryNativeDir ( & Dir );
184 if ( RCt == 0 ) {
185 RCt = Write
186 ? KDirectoryOpenFileWrite ( Dir, File, "%s", Name )
187 : KDirectoryOpenFileRead ( Dir, ( const KFile ** ) File, "%s", Name )
188 ;
189 KDirectoryRelease ( Dir );
190 }
191
192 return RCt;
193 } /* checkOpenFile () */
194
195 static
196 bool
checkFileSize(const char * FileName,uint64_t Size)197 checkFileSize ( const char * FileName, uint64_t Size )
198 {
199 rc_t RCt;
200 KDirectory * Dir;
201 uint64_t FileSize;
202
203 RCt = 0;
204 Dir = NULL;
205 FileSize = 0;
206
207 printf ( "[SIZ] [%s] [%llu]\n", FileName, ( long long unsigned int ) Size );
208
209 RCt = KDirectoryNativeDir ( & Dir );
210 if ( RCt == 0 ) {
211 RCt = KDirectoryFileSize ( Dir, & FileSize, "%s", FileName );
212
213 KDirectoryRelease ( Dir );
214 }
215
216 return RCt == 0 ? ( FileSize == Size ) : false;
217 } /* checkFileSize () */
218
219 static
220 bool
checkFileDelete(const char * FileName)221 checkFileDelete ( const char * FileName )
222 {
223 rc_t RCt;
224 KDirectory * Dir;
225
226 RCt = 0;
227 Dir = NULL;
228
229 printf ( "[REM] [%s]\n", FileName );
230
231 RCt = KDirectoryNativeDir ( & Dir );
232 if ( RCt == 0 ) {
233 RCt = KDirectoryRemove ( Dir, "%s", FileName );
234
235 KDirectoryRelease ( Dir );
236 }
237
238 return RCt;
239 } /* checkFileDelete () */
240
241 static
242 rc_t
checkFileSetSize(KFile * File,size_t Size)243 checkFileSetSize ( KFile * File, size_t Size )
244 {
245 printf ( "[SET] [%s] SZ[%lu]\n", FileName, Size );
246
247 return KFileSetSize ( File, Size );
248 } /* checkFileSetSize () */
249
250
TEST_CASE(KAppendFile_read_write)251 TEST_CASE(KAppendFile_read_write)
252 {
253 KFile * File;
254 KFile * AFile;
255 uint64_t FileSize;
256 uint64_t NewSize;
257
258 File = NULL;
259 AFile = NULL;
260 FileSize = 0;
261 NewSize = 0;
262
263 printf ( "\n[[[[TST:1] [Simple read / write]\n" );
264 /* Simple read/write file
265 */
266 FileSize = 64;
267 REQUIRE_RC(checkMakeFile(FileName, FileSize));
268
269 REQUIRE(checkFileSize(FileName, FileSize));
270
271 REQUIRE_RC(checkOpenFile ( & File, FileName, true ));
272
273 REQUIRE_RC(KFileMakeAppend(&AFile, File));
274 KFileRelease ( File );
275
276 REQUIRE_RC(checkWriteFile(AFile, 0, FileSize));
277 REQUIRE_RC(KFileSize(AFile, &NewSize));
278 REQUIRE(FileSize == NewSize);
279 REQUIRE_RC(checkReadFile(AFile, 2, 22));
280
281
282 KFileRelease ( AFile );
283 REQUIRE(checkFileSize(FileName, FileSize * 2));
284
285 REQUIRE_RC(checkFileDelete(FileName));
286 }
287
TEST_CASE(KAppendFile_read_write_zerosize)288 TEST_CASE(KAppendFile_read_write_zerosize)
289 {
290 KFile * File;
291 KFile * AFile;
292 uint64_t FileSize;
293 uint64_t NewSize;
294
295 File = NULL;
296 AFile = NULL;
297 FileSize = 0;
298 NewSize = 0;
299
300 printf ( "\n[[[[TST:2] [Simple read / write on empty file]\n" );
301 /* Simple read/write file
302 */
303 FileSize = 64;
304 REQUIRE_RC(checkMakeFile(FileName, 0));
305
306 REQUIRE(checkFileSize(FileName, 0));
307
308 REQUIRE_RC(checkOpenFile ( & File, FileName, true ));
309
310 REQUIRE_RC(KFileMakeAppend(&AFile, File));
311 KFileRelease ( File );
312
313 REQUIRE_RC(checkWriteFile(AFile, 0, FileSize));
314 REQUIRE_RC(KFileSize(AFile, &NewSize));
315 REQUIRE(FileSize == NewSize);
316 REQUIRE_RC(checkReadFile(AFile, 2, 22));
317
318
319 KFileRelease ( AFile );
320 REQUIRE(checkFileSize(FileName, FileSize));
321
322 REQUIRE_RC(checkFileDelete(FileName));
323 }
324
TEST_CASE(KAppendFile_set_size)325 TEST_CASE(KAppendFile_set_size)
326 {
327 KFile * File;
328 KFile * AFile;
329 uint64_t FileSize;
330 uint64_t NewSize;
331
332 File = NULL;
333 AFile = NULL;
334 FileSize = 0;
335 NewSize = 0;
336
337 printf ( "\n[[[[TST:3] [Setting file size]\n" );
338
339 FileSize = 64;
340 REQUIRE_RC(checkMakeFile(FileName, FileSize));
341
342 REQUIRE(checkFileSize(FileName, FileSize));
343
344 REQUIRE_RC(checkOpenFile ( & File, FileName, true ));
345
346 REQUIRE_RC(KFileMakeAppend(&AFile, File));
347 KFileRelease ( File );
348
349 REQUIRE_RC(checkWriteFile(AFile, 0, FileSize));
350
351 REQUIRE_RC(KFileSize(AFile, &NewSize));
352 REQUIRE(FileSize == NewSize);
353
354 REQUIRE_RC(checkFileSetSize(AFile, FileSize / 2));
355 REQUIRE_RC(KFileSize(AFile, &NewSize));
356 REQUIRE(FileSize / 2 == NewSize);
357
358 KFileRelease ( AFile );
359 REQUIRE(checkFileSize(FileName, FileSize + (FileSize / 2)));
360
361 REQUIRE_RC(checkFileDelete(FileName));
362 }
363
364 //////////////////////////////////////////// Main
365
366 extern "C"
367 {
368
KAppVersion(void)369 ver_t CC KAppVersion ( void )
370 {
371 return 0x1000000;
372 }
373
UsageSummary(const char * prog_name)374 rc_t CC UsageSummary (const char * prog_name)
375 {
376 return 0;
377 }
378
Usage(const Args * args)379 rc_t CC Usage ( const Args * args)
380 {
381 return 0;
382 }
383
384 const char UsageDefaultName[] = "test-appendfile";
385
KMain(int argc,char * argv[])386 rc_t CC KMain ( int argc, char *argv [] )
387 {
388 rc_t rc=AppendFileTestSuite(argc, argv);
389 return rc;
390 }
391
392 }
393