feisty meow concerns codebase 2.140
test_byte_filer.cpp
Go to the documentation of this file.
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
25#include <filesystem/filename.h>
28#include <mathematics/chaos.h>
32#include <unit_test/unit_base.h>
33
34using namespace application;
35using namespace basis;
36using namespace configuration;
37using namespace mathematics;
38using namespace filesystem;
39using namespace loggers;
40using namespace structures;
41using namespace textual;
42using namespace timely;
43using namespace unit_test;
44
45#define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger::get(), s)
46
47//#define DEBUG_BYTE_FILER
48 // uncomment for noisy test run.
49
50class test_byte_filer : virtual public unit_base, virtual public application_shell
51{
52public:
53 test_byte_filer() : application_shell() {}
54 DEFINE_CLASS_NAME("test_byte_filer");
55 int run_simple_test();
56 int run_file_scan();
57 virtual int execute();
58};
59
61{
62 const char *TEST_FILE_BASE = "/zz_garbage";
63 const char *TEST_FILE_SUFFIX = ".txt";
64 static astring __hidden_filename;
65 if (!__hidden_filename) {
66 __hidden_filename = environment::TMP();
67 if (!__hidden_filename) __hidden_filename = "/tmp";
68 // try to create it just in case it wasn't there already.
69 directory::make_directory(__hidden_filename);
70 __hidden_filename += TEST_FILE_BASE;
71 __hidden_filename += a_sprintf("%d", chaos().inclusive(0, 65535));
72 __hidden_filename += TEST_FILE_SUFFIX;
73 }
74 return __hidden_filename;
75}
76
77int test_byte_filer::run_simple_test()
78{
79 FUNCDEF("run_simple_test");
80#ifdef DEBUG_BYTE_FILER
81 LOG("ahoy, beginning file test...");
82 LOG(astring("test file is ") + TEST_FILE());
83#endif
84
86
87//hmmm: move to t_filename.
88 // test filename's exist operation.
89 byte_filer garbage(TEST_FILE().s(), "wb");
90 garbage.write("oy.\n");
91 garbage.close();
92 filename test1(TEST_FILE());
93 ASSERT_TRUE(test1.exists(), "exists test file should exist");
94 filename test2("c:\\this_file_shouldNt_exist_ever.txt");
95 ASSERT_FALSE(test2.exists(), "weird file should not existed");
96 // test again to make sure it didn't create it.
97 ASSERT_FALSE(test2.exists(), "weird file should still not exist");
98 test1.unlink();
99
100 int block_size = randomizer.inclusive(3000, 30000);
101#ifdef DEBUG_BYTE_FILER
102 LOG(a_sprintf("block size=%d", block_size));
103#endif
104 abyte *original_block = new abyte[block_size];
105 for (int i = 0; i < block_size; i++)
106 original_block[i] = abyte(randomizer.inclusive(32, 126));
107 unsigned int original_checksum
108 = checksums::bizarre_checksum((abyte *)original_block, block_size);
109 if (original_checksum) {} // compiler quieting.
110#ifdef DEBUG_BYTE_FILER
111 LOG(a_sprintf("random block checksum=%d", original_checksum));
112#endif
113 {
114 byte_array to_stuff_in_file(block_size, original_block);
115 delete [] original_block;
116 byte_filer fred(TEST_FILE(), "w+");
117 fred.write(to_stuff_in_file);
118 }
119#ifdef DEBUG_BYTE_FILER
120 LOG(astring("about to compare file to checksum"));
121#endif
122 {
123 abyte *temp_array = new abyte[21309];
124 byte_array to_fake_stuff(21309, temp_array);
125 delete [] temp_array;
126 byte_filer fred(TEST_FILE(), "r");
127#ifdef DEBUG_BYTE_FILER
128 LOG(astring("about to try writing to file"));
129#endif
130 int should_be_failure = fred.write(to_fake_stuff);
131 ASSERT_EQUAL(should_be_failure, 0, "write on read only, should not succeed");
132
133#ifdef DEBUG_BYTE_FILER
134 LOG(a_sprintf("about to try reading from file %d bytes", block_size * 2));
135#endif
136 byte_array file_contents;
137 int bytes_read = fred.read(file_contents, block_size * 2);
138 ASSERT_EQUAL(bytes_read, block_size, "reading entire file should get proper size");
139 un_int check_2 = checksums::bizarre_checksum((abyte *)file_contents.access(), file_contents.length());
140 ASSERT_EQUAL((int)check_2, (int)original_checksum, "should read correct contents for checksum");
141 }
142
143#define FACTOR 1354
144
145 {
146 int numpacs = number_of_packets(block_size, FACTOR);
147 byte_filer fred(TEST_FILE(), "rb");
150 int whole_size = 0;
151 for (int i = 0; i < numpacs; i++) {
152 byte_array blob_i;
153 int bytes_in = fred.read(blob_i, FACTOR);
154 ASSERT_FALSE(bytes_in > FACTOR, "we should never somehow read in more than we asked for");
155 whole_size += blob_i.length();
156 }
157 ASSERT_EQUAL(whole_size, fred.length(), "chunking comparison should see sizes as same");
158 }
159
160// test writing out a copy and comparing them... there's no == on files!
161
162 ASSERT_TRUE(filename(TEST_FILE()).unlink(), "cleanup should be able to remove temporary file");
163
164 // it seems everything worked during our tests.
165 return 0;
166}
167
168int test_byte_filer::run_file_scan()
169{
170 FUNCDEF("run_file_scan");
172
174 files.zap(0, 0); // toss the first element since that's our app filename.
175
176 if (!files.length()) {
177 // pretend they gave us the list of files in the current directory. some of
178 // these might fail if they're locked up.
180 directory dir(tmpdir);
181 for (int i = 0; i < dir.files().length(); i++) {
182 // skip text files since we use those right here.
183 if ( (dir.files()[i].ends(".txt")) || (dir.files()[i].ends(".txt")) )
184 continue;
185 astring chewed_string = tmpdir + "/" + dir.files()[i];
186 files += chewed_string;
187 }
188//LOG(astring("added files since no cmd args: ") + files.text_form());
189 }
190
191 byte_array data_found;
192 for (int i = 0; i < files.length(); i++) {
193 astring curr = files[i];
194// LOG(a_sprintf("file %d: ", i) + curr);
195 byte_filer test(curr, "rb");
196 if (!test.good()) {
197 LOG(astring("good check: ") + curr + " cannot be opened. is this bad?");
198 continue;
199 }
200
201 // check that we get the expected position report from scooting to the
202 // end of a file.
203 test.seek(0, byte_filer::FROM_END);
204 ASSERT_EQUAL((int)test.tell(), (int)test.length(), "seek check should get to end as expected");
206
207 size_t len = test.length();
208//log(a_sprintf("file len is %.0f", double(len)));
209 size_t posn = 0;
210 while ( (posn < len) && !test.eof() ) {
211 size_t readlen = randomizer.inclusive(1, 256 * KILOBYTE);
212//log(a_sprintf("read %u bytes, posn now %d bytes", readlen, posn));
213 int bytes_read = int(test.read(data_found, int(readlen)));
214 ASSERT_TRUE(bytes_read >= 0, "reading should not fail to read some bytes");
215 if (bytes_read > 0) {
216 posn += bytes_read;
217 }
218 }
219 ASSERT_TRUE(test.eof(), "eof check should see us at eof");
220 ASSERT_EQUAL((int)posn, (int)len, "eof check should be at right position");
221// log(astring("successfully read ") + curr);
222 }
223
224 return 0;
225}
226
227int test_byte_filer::execute()
228{
229 FUNCDEF("execute");
230 int ret = run_simple_test();
231 if (ret) return ret; // failed.
232 ret = run_file_scan();
233 if (ret) return ret; // failed here.
234
235 return final_report();
236}
237
238HOOPLE_MAIN(test_byte_filer, )
239
#define unlink
Definition Xos2defs.h:45
The application_shell is a base object for console programs.
virtual int execute()=0
< retrieves the command line from the /proc hierarchy on linux.
application_shell()
constructs an application_shell to serve as the root of the program.
a_sprintf is a specialization of astring that provides printf style support.
Definition astring.h:440
contents * access()
A non-constant access of the underlying C-array. BE REALLY CAREFUL.
Definition array.h:175
int length() const
Returns the current reported length of the allocated C array.
Definition array.h:115
Provides a dynamically resizable ASCII character string.
Definition astring.h:35
A very common template for a dynamic array of bytes.
Definition byte_array.h:36
static astring TMP()
provides a single place to get the temporary directory.
static basis::astring current_directory()
returns the current directory as reported by the operating system.
Provides file managment services using the standard I/O support.
Definition byte_filer.h:32
@ FROM_START
offset is from the beginning of the file.
Definition byte_filer.h:94
@ FROM_END
offset is from the end of the file.
Definition byte_filer.h:95
Implements a scanner that finds all filenames in the directory specified.
Definition directory.h:27
static bool make_directory(const basis::astring &path)
returns true if the directory "path" could be created.
Provides operations commonly needed on file names.
Definition filename.h:64
a platform-independent way to acquire random numbers in a specific range.
Definition chaos.h:51
static unsigned int bizarre_checksum(const basis::abyte *data, int length)
A different type of checksum with somewhat unknown properties.
Definition checksums.cpp:25
An array of strings with some additional helpful methods.
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Definition enhance_cpp.h:42
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition enhance_cpp.h:54
Provides macros that implement the 'main' program of an application.
#define HOOPLE_MAIN(obj_name, obj_args)
options that should work for most unix and linux apps.
Definition hoople_main.h:61
Implements an application lock to ensure only one is running at once.
char ** _global_argv
The guards collection helps in testing preconditions and reporting errors.
Definition array.h:30
type number_of_packets(type message_size, type packet_size)
Reports number of packets needed given a total size and the packet size.
Definition functions.h:137
unsigned char abyte
A fairly important unit which is seldom defined...
Definition definitions.h:51
unsigned int un_int
Abbreviated name for unsigned integers.
Definition definitions.h:62
const int KILOBYTE
Number of bytes in a kilobyte.
A platform independent way to obtain the timestamp of a file.
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
Definition averager.h:21
A dynamic container class that holds any kind of object via pointers.
Definition amorph.h:55
#include <time.h>
Useful support functions for unit testing, especially within hoople.
Definition unit_base.cpp:35
#define randomizer()
#define LOG(s)
#define FACTOR
const astring & TEST_FILE()
#define test(expr)
#define ASSERT_EQUAL(a, b, test_name)
Definition unit_base.h:38
#define ASSERT_TRUE(a, test_name)
Definition unit_base.h:46
#define ASSERT_FALSE(a, test_name)
Definition unit_base.h:50