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