first check-in of feisty meow codebase. many things broken still due to recent
[feisty_meow.git] / core / library / tests_filesystem / test_byte_filer.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : test_byte_filer                                                   *
4 *  Author : Chris Koeritz                                                     *
5 *                                                                             *
6 *******************************************************************************
7 * Copyright (c) 1991-$now By Author.  This program is free software; you can  *
8 * redistribute it and/or modify it under the terms of the GNU General Public  *
9 * License as published by the Free Software Foundation; either version 2 of   *
10 * the License or (at your option) any later version.  This is online at:      *
11 *     http://www.fsf.org/copyleft/gpl.html                                    *
12 * Please send any updates to: fred@gruntose.com                               *
13 \*****************************************************************************/
14
15 #include <basis/byte_array.h>
16 #include <mathematics/chaos.h>
17 #include <basis/functions.h>
18 #include <basis/guards.h>
19 #include <basis/astring.h>
20
21 #include <application/hoople_main.h>
22 #include <configuration/application_configuration.h>
23 #include <filesystem/byte_filer.h>
24 #include <filesystem/directory.h>
25 #include <filesystem/filename.h>
26 #include <loggers/critical_events.h>
27 #include <loggers/program_wide_logger.h>
28 #include <mathematics/chaos.h>
29 #include <structures/checksums.h>
30 #include <structures/static_memory_gremlin.h>
31 #include <structures/string_array.h>
32 #include <unit_test/unit_base.h>
33
34 using namespace application;
35 using namespace basis;
36 using namespace configuration;
37 using namespace mathematics;
38 using namespace filesystem;
39 using namespace loggers;
40 using namespace structures;
41 using namespace textual;
42 using namespace timely;
43 using namespace unit_test;
44
45 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
46
47 class test_byte_filer : virtual public unit_base, virtual public application_shell
48 {
49 public:
50   test_byte_filer() : application_shell() {}
51   DEFINE_CLASS_NAME("test_byte_filer");
52   int run_simple_test();
53   int run_file_scan();
54   virtual int execute();
55 };
56
57 const astring &TEST_FILE()
58 {
59   const char *TEST_FILE_BASE = "/zz_garbage.txt";
60   static astring __hidden_filename;
61   if (!__hidden_filename) {
62     __hidden_filename = environment::get("TMP");
63     if (!__hidden_filename) __hidden_filename = "/tmp";
64     __hidden_filename += astring(TEST_FILE_BASE);
65   }
66   return __hidden_filename;
67 }
68
69 int test_byte_filer::run_simple_test()
70 {
71   FUNCDEF("run_simple_test");
72 #ifdef DEBUG
73   LOG("ahoy, beginning file test...");
74   LOG(astring("test file is ") + TEST_FILE());
75 #endif
76
77   chaos randomizer;
78
79 //hmmm: move to t_filename.
80   // test filename's exist operation.
81   byte_filer garbage(TEST_FILE().s(), "wb");
82   garbage.write("oy.\n");
83   garbage.close();
84   filename test1(TEST_FILE());
85   ASSERT_TRUE(test1.exists(), "exists test file should exist");
86   filename test2("c:\\this_file_shouldNt_exist_ever.txt");
87   ASSERT_FALSE(test2.exists(), "weird file should not existed");
88   // test again to make sure it didn't create it.
89   ASSERT_FALSE(test2.exists(), "weird file should still not exist");
90   test1.unlink();
91
92   int block_size = randomizer.inclusive(3000, 30000);
93 #ifdef DEBUG
94   LOG(a_sprintf("block size=%d", block_size));
95 #endif
96   abyte *original_block = new abyte[block_size];
97   for (int i = 0; i < block_size; i++)
98     original_block[i] = abyte(randomizer.inclusive(32, 126));
99   unsigned int original_checksum
100       = checksums::bizarre_checksum((abyte *)original_block, block_size);
101   if (original_checksum) {} // compiler quieting.
102 #ifdef DEBUG
103   LOG(a_sprintf("random block checksum=%d", original_checksum));
104 #endif
105   {
106     byte_array to_stuff_in_file(block_size, original_block);
107     delete [] original_block;
108     byte_filer fred(TEST_FILE(), "w+");
109     fred.write(to_stuff_in_file);
110   }
111 #ifdef DEBUG
112   LOG(astring("about to compare file to checksum"));
113 #endif
114   {
115     abyte *temp_array = new abyte[21309];
116     byte_array to_fake_stuff(21309, temp_array);
117     delete [] temp_array;
118     byte_filer fred(TEST_FILE(), "r");
119 #ifdef DEBUG
120     LOG(astring("about to try writing to file"));
121 #endif
122     int should_be_failure = fred.write(to_fake_stuff);
123     ASSERT_EQUAL(should_be_failure, 0, "write on read only, should not succeed");
124
125 ///    int fredsize = int(fred.size());
126 ///    fred.chunk_factor(fredsize);
127
128 #ifdef DEBUG
129     LOG(a_sprintf("about to try reading from file %d bytes", fredsize));
130 #endif
131     byte_array file_contents;
132     int bytes_read = fred.read(file_contents, block_size * 2);
133     ASSERT_EQUAL(bytes_read, block_size, "reading entire file should get proper size");
134     un_int check_2 = checksums::bizarre_checksum((abyte *)file_contents.access(), file_contents.length());
135     ASSERT_EQUAL((int)check_2, (int)original_checksum, "should read correct contents for checksum");
136   }
137
138 #define FACTOR 1354
139
140   {
141     int numpacs = number_of_packets(block_size, FACTOR);
142     byte_filer fred(TEST_FILE(), "rb");
143 ///file::READ_ONLY);
144 ///    fred.chunk_factor(FACTOR);
145     int whole_size = 0;
146     for (int i = 0; i < numpacs; i++) {
147       byte_array blob_i;
148       int bytes_in = fred.read(blob_i, FACTOR);
149       ASSERT_FALSE(bytes_in > FACTOR, "we should never somehow read in more than we asked for");
150       whole_size += blob_i.length();
151     }
152     ASSERT_EQUAL(whole_size, fred.length(), "chunking comparison should see sizes as same");
153   }
154
155 // test writing out a copy and comparing them... there's no == on files!
156
157   ASSERT_TRUE(filename(TEST_FILE()).unlink(), "cleanup should be able to remove temporary file");
158
159   // it seems everything worked during our tests.
160   return 0;
161 }
162
163 int test_byte_filer::run_file_scan()
164 {
165   FUNCDEF("run_file_scan");
166   chaos randomizer;
167
168   string_array files(_global_argc, (const char **)_global_argv);
169   files.zap(0, 0);  // toss the first element since that's our app filename.
170
171   if (!files.length()) {
172     // pretend they gave us the list of files in the TMP directory.  some of
173     // these might fail if they're locked up.
174 //    astring tmpdir = environment::get("TMP");
175     astring tmpdir = application_configuration::current_directory();
176     directory dir(tmpdir);
177     for (int i = 0; i < dir.files().length(); i++) {
178       // skip text files since we use those right here.
179       if ( (dir.files()[i].ends(".txt")) || (dir.files()[i].ends(".txt")) )
180         continue;
181       astring chewed_string = tmpdir + "/" + dir.files()[i];
182       files += chewed_string;
183     }
184 //LOG(astring("added files since no cmd args: ") + files.text_form());
185   }
186
187   byte_array data_found;
188   for (int i = 0; i < files.length(); i++) {
189     astring curr = files[i];
190 //    LOG(a_sprintf("file %d: ", i) + curr);
191     byte_filer test(curr, "rb");
192     if (!test.good()) {
193       LOG(astring("good check: ") + curr + " cannot be opened.  is this bad?");
194       continue;
195     }
196
197     // check that we get the expected position report from scooting to the
198     // end of a file.
199     test.seek(0, byte_filer::FROM_END);
200     ASSERT_EQUAL((int)test.tell(), (int)test.length(), "seek check should get to end as expected");
201     test.seek(0, byte_filer::FROM_START);
202
203     size_t len = test.length();
204 //log(a_sprintf("file len is %.0f", double(len)));
205     size_t posn = 0;
206     while ( (posn < len) && !test.eof() ) {
207       size_t readlen = randomizer.inclusive(1, 256 * KILOBYTE);
208 //log(a_sprintf("read %u bytes, posn now %d bytes", readlen, posn));
209       int bytes_read = int(test.read(data_found, int(readlen)));
210       ASSERT_TRUE(bytes_read >= 0, "reading should not fail to read some bytes");
211       if (bytes_read > 0) {
212         posn += bytes_read;
213       }
214     }
215     ASSERT_TRUE(test.eof(), "eof check should see us at eof");
216     ASSERT_EQUAL((int)posn, (int)len, "eof check should be at right position");
217 //    log(astring("successfully read ") + curr);
218   }
219
220   return 0;
221 }
222
223 int test_byte_filer::execute()
224 {
225 //  FUNCDEF("execute");
226   int ret = run_simple_test();
227   if (ret) return ret;  // failed.
228   ret = run_file_scan();
229   if (ret) return ret;  // failed here.
230
231   return final_report();
232 }
233
234 HOOPLE_MAIN(test_byte_filer, )
235