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 #include <vdb/manager.h> // VDBManager
26 #include <vdb/vdb-priv.h>
27 
28 #include <ktst/unit_test.hpp> // TEST_CASE
29 #include <vfs/path.h>
30 #include <vfs/manager.h>
31 #include <klib/text.h>
32 #include <klib/out.h>
33 #include <klib/printf.h>
34 #include <klib/time.h>
35 #include <kfs/directory.h>
36 #include <kfs/file.h>
37 #include <kfg/config.h>
38 
39 #include <sysalloc.h>
40 #include <cstdlib>
41 #include <stdexcept>
42 
43 using namespace std;
44 
45 TEST_SUITE( VDB_3061 )
46 
47 const char HomeSub[] = "test_root_history";
48 char new_home[ 4096 ];
49 
create_cache_file(KDirectory * dir,const char * path,const char * sub,const char * name,int64_t age_in_seconds)50 static rc_t create_cache_file( KDirectory * dir, const char * path, const char * sub, const char * name,
51                                int64_t age_in_seconds )
52 {
53     KFile * f;
54     rc_t rc = KDirectoryCreateFile( dir, &f, false, 0775, kcmInit, "%s/ncbi/%s/%s", path, sub, name );
55     if ( rc == 0 )
56     {
57         KFileRelease( f );
58 
59         KTime_t date = KTimeStamp() - age_in_seconds;
60         rc = KDirectorySetDate ( dir, false, date, "%s/ncbi/%s/%s", path, sub, name );
61     }
62     return rc;
63 }
64 
create_repo_dirs(KDirectory * dir,const char * path,const char * sub,uint32_t age_in_days,int32_t offset_in_seconds)65 static rc_t create_repo_dirs( KDirectory * dir, const char * path, const char * sub,
66                               uint32_t age_in_days, int32_t offset_in_seconds )
67 {
68     rc_t rc = KDirectoryCreateDir( dir, 0775, kcmInit | kcmParents, "%s/ncbi/%s/files", path, sub );
69     if ( rc == 0 )
70         rc = KDirectoryCreateDir( dir, 0775, kcmInit | kcmParents, "%s/ncbi/%s/nannot", path, sub );
71     if ( rc == 0 )
72         rc = KDirectoryCreateDir( dir, 0775, kcmInit | kcmParents, "%s/ncbi/%s/refseq", path, sub );
73     if ( rc == 0 )
74         rc = KDirectoryCreateDir( dir, 0775, kcmInit | kcmParents, "%s/ncbi/%s/sra", path, sub );
75     if ( rc == 0 )
76         rc = KDirectoryCreateDir( dir, 0775, kcmInit | kcmParents, "%s/ncbi/%s/wgs", path, sub );
77     if ( rc == 0 )
78     {
79         int64_t age_in_seconds = age_in_days;
80         age_in_seconds *= ( 60 * 60 * 24 );
81         age_in_seconds += offset_in_seconds;
82         rc = create_cache_file( dir, path, sub, "/sra/file1.txt", age_in_seconds );
83     }
84     return rc;
85 }
86 
87 
clear_out(const char * path)88 static void clear_out( const char * path )
89 {
90     /* clear the temp. home-directory */
91     KDirectory * dir;
92     rc_t rc = KDirectoryNativeDir( &dir );
93     if ( rc == 0 )
94     {
95 #ifdef WINDOWS
96         rc = KDirectoryRemove( dir, true, "%s", path );
97 #else
98         rc = KDirectoryRemove( dir, true, "%s", path );
99 #endif
100         KDirectoryRelease( dir );
101     }
102 }
103 
TEST_CASE(CLEAR_CACHE_1)104 TEST_CASE( CLEAR_CACHE_1 )
105 {
106 	REQUIRE_RC( KOutMsg( "running: CLEAR_CACHE_1\n" ) );
107 
108     /* create a repository-structure equivalent to the config-values, with 3 files in it */
109     KDirectory * dir;
110     REQUIRE_RC( KDirectoryNativeDir( &dir ) );
111     REQUIRE_RC( create_repo_dirs( dir, new_home, "public", 10, 0 ) ); /* 10 days old */
112     REQUIRE_RC( create_repo_dirs( dir, new_home, "dbGaP-2956", 4, 0 ) ); /* 4 days old */
113     REQUIRE_RC( create_repo_dirs( dir, new_home, "dbGaP-4831", 5, -5 ) ); /* 5 days - 5 seconds old */
114     REQUIRE_RC( KDirectoryRelease ( dir ) );
115 
116     /* we run the new function VDBManagerDeleteCacheOlderThan() with a 5-day threshold */
117     const VDBManager * vdb_mgr;
118     REQUIRE_RC( VDBManagerMakeRead( &vdb_mgr, NULL ) );
119     REQUIRE_RC( VDBManagerDeleteCacheOlderThan ( vdb_mgr, 5 ) );
120     REQUIRE_RC( VDBManagerRelease ( vdb_mgr ) );
121 
122     /* now the 10 day old one should have disappeared, the other 2 are still there */
123     REQUIRE_RC( KDirectoryNativeDir( &dir ) );
124     uint32_t pt1 = KDirectoryPathType( dir, "%s/ncbi/public/sra/file1.txt", new_home );
125     REQUIRE_EQ( pt1, (uint32_t)kptNotFound );
126     uint32_t pt2 = KDirectoryPathType( dir, "%s/ncbi/dbGaP-2956/sra/file1.txt", new_home );
127     REQUIRE_EQ( pt2, (uint32_t)kptFile );
128     uint32_t pt3 = KDirectoryPathType( dir, "%s/ncbi/dbGaP-4831/sra/file1.txt", new_home );
129     REQUIRE_EQ( pt3, (uint32_t)kptFile );
130     REQUIRE_RC( KDirectoryRelease ( dir ) );
131 
132 	REQUIRE_RC( KOutMsg( "done: CLEAR_CACHE_1\n" ) );
133 }
134 
135 
TEST_CASE(CLEAR_CACHE_2)136 TEST_CASE( CLEAR_CACHE_2 )
137 {
138 	REQUIRE_RC( KOutMsg( "running: CLEAR_CACHE_2\n" ) );
139 
140 	REQUIRE_RC( KOutMsg( "clearing: %s\n", new_home ) );
141 	clear_out( new_home );
142 
143     const VDBManager * vdb_mgr;
144     REQUIRE_RC( VDBManagerMakeRead( &vdb_mgr, NULL ) );
145     REQUIRE_RC( VDBManagerDeleteCacheOlderThan ( vdb_mgr, 0 ) );
146     REQUIRE_RC( VDBManagerRelease ( vdb_mgr ) );
147 
148 	REQUIRE_RC( KOutMsg( "done: CLEAR_CACHE_2\n" ) );
149 }
150 
151 
write_root(KConfig * cfg,const char * base,const char * cat,const char * sub_cat)152 static rc_t write_root( KConfig *cfg, const char * base, const char * cat, const char * sub_cat )
153 {
154     char key[ 256 ];
155     size_t num_writ;
156     rc_t rc = string_printf ( key, sizeof key, &num_writ, "/repository/user/%s/%s/root", cat, sub_cat );
157     if ( rc == 0 )
158     {
159         char value[ 256 ];
160         rc = string_printf ( value, sizeof value, &num_writ, "%s/ncbi/%s", base, sub_cat );
161         if ( rc == 0 )
162             rc = KConfigWriteString( cfg, key, value );
163     }
164     return rc;
165 }
166 
167 
write_dflt_path(KConfig * cfg,const char * base)168 static rc_t write_dflt_path( KConfig *cfg, const char * base )
169 {
170     char value[ 256 ];
171     size_t num_writ;
172     rc_t rc = string_printf ( value, sizeof value, &num_writ, "%s/ncbi", base );
173     if ( rc == 0 )
174         rc = KConfigWriteString( cfg, "/repository/user/default-path", value );
175     return rc;
176 }
177 
178 #ifdef WINDOWS
convert_sys_path(const char * sys_path)179 static char * convert_sys_path( const char * sys_path )
180 {
181     char * res = NULL;
182     VFSManager * vfs_mgr;
183     rc_t rc = VFSManagerMake ( &vfs_mgr );
184     if ( rc == 0 )
185     {
186         VPath * p;
187         rc = VFSManagerMakeSysPath ( vfs_mgr, &p, sys_path );
188         if ( rc == 0 )
189         {
190             const String * S;
191             rc = VPathMakeString( p, &S );
192             if ( rc == 0 )
193                 res = string_dup ( S->addr, S->size );
194             VPathRelease( p );
195         }
196         VFSManagerRelease( vfs_mgr );
197     }
198     return res;
199 }
200 #endif
201 
create_test_config(KConfig ** cfg,const char * base)202 static rc_t create_test_config( KConfig **cfg, const char * base )
203 {
204     rc_t rc = KConfigMake ( cfg, NULL );
205     if ( rc == 0 )
206     {
207 #ifdef WINDOWS
208         const char * cfg_base = convert_sys_path( base );
209 #else
210         const char * cfg_base = base;
211 #endif
212         if ( cfg_base != NULL )
213         {
214             rc = write_root( *cfg, cfg_base, "main", "public" );
215             if ( rc == 0 )
216                 rc = write_root( *cfg, cfg_base, "protected", "dbGaP-2956" );
217             if ( rc == 0 )
218                 rc = write_root( *cfg, cfg_base, "protected", "dbGaP-4831" );
219             if ( rc == 0 )
220                 rc = write_dflt_path( *cfg, cfg_base );
221 #ifdef WINDOWS
222             free( ( void * ) cfg_base );
223 #endif
224         }
225     }
226     return rc;
227 }
228 
229 char * org_home;
230 char new_home_buffer[ 4096 ]; /* buffer for putenv has to stay alive! */
231 
prepare_test(KConfig ** cfg,const char * sub)232 static rc_t prepare_test( KConfig **cfg, const char * sub )
233 {
234 	size_t num_writ;
235 #ifdef WINDOWS
236     org_home = getenv ( "USERPROFILE" );
237     rc_t rc = string_printf ( new_home, sizeof new_home, &num_writ, "%s\\%s", org_home, sub );
238 #else
239 	org_home = getenv( "HOME" );
240     rc_t rc = string_printf ( new_home, sizeof new_home, &num_writ, "%s/%s", org_home, sub );
241 #endif
242     if ( rc == 0 )
243 #ifdef WINDOWS
244         rc = string_printf ( new_home_buffer, sizeof new_home_buffer, &num_writ, "HOME=%s", new_home );
245 #else
246         rc = string_printf ( new_home_buffer, sizeof new_home_buffer, &num_writ, "USERPROFILE=%s", new_home );
247 #endif
248     if ( rc == 0 )
249         rc = putenv( new_home_buffer );
250     if ( rc == 0 )
251         rc = create_test_config( cfg, new_home );
252     return rc;
253 }
254 
finish_test(const char * sub)255 void finish_test( const char * sub )
256 {
257     /* clear the temp. home-directory */
258     KDirectory * dir;
259     rc_t rc = KDirectoryNativeDir( &dir );
260     if ( rc == 0 )
261     {
262 #ifdef WINDOWS
263         rc = KDirectoryRemove( dir, true, "%s/%s", org_home, sub );
264 #else
265         rc = KDirectoryRemove( dir, true, "%s\\%s", org_home, sub );
266 #endif
267         rc = KDirectoryRemove( dir, true, "%s", new_home );
268         KDirectoryRelease( dir );
269     }
270 }
271 
272 //////////////////////////////////////////// Main
273 extern "C"
274 {
275 
276 #include <kapp/args.h>
277 
KAppVersion(void)278 ver_t CC KAppVersion ( void ) { return 0x1000000; }
UsageSummary(const char * progname)279 rc_t CC UsageSummary ( const char * progname ) { return 0; }
Usage(const Args * args)280 rc_t CC Usage ( const Args * args ) { return 0; }
281 const char UsageDefaultName[] = "test-VDB-3060";
282 
KMain(int argc,char * argv[])283 rc_t CC KMain ( int argc, char *argv [] )
284 {
285     KConfigDisableUserSettings();
286     const char HomeSub[] = "test_root_history";
287     KConfig *cfg;
288     rc_t rc = prepare_test( &cfg, HomeSub );
289     if ( rc == 0 )
290         rc = VDB_3061( argc, argv );
291     finish_test( HomeSub );
292     KConfigRelease ( cfg );
293     return rc;
294 }
295 
296 }
297