Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test_archive_builder.h
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "lib/self_test.h"
24 
25 #include "lib/base32.h"
26 #include "lib/res/file/path.h"
27 #include "lib/res/file/fp_posix.h"
28 #include "lib/res/file/file_cache.h"
29 #include "lib/res/file/vfs/vfs.h"
30 #include "lib/res/file/archive/archive.h"
31 #include "lib/res/file/archive/archive_builder.h"
32 #include "lib/res/h_mgr.h"
33 #include "lib/res/mem.h"
34 #include "lib/rand.h"
35 
36 class TestArchiveBuilder : public CxxTest::TestSuite
37 {
38  const char* const archive_fn;
39  static const size_t NUM_FILES = 30;
40  static const size_t MAX_FILE_SIZE = 20000;
41 
42  std::set<const char*> existing_names;
43  const char* gen_random_name()
44  {
45  // 10 chars is enough for (10-1)*5 bits = 45 bits > u32
46  char name_tmp[10];
47 
48  for(;;)
49  {
50  u32 rand_num = rand(0, 100000);
51  base32(4, (const u8*)&rand_num, (u8*)name_tmp);
52 
53  // store filename in atom pool
54  const char* atom_fn = file_make_unique_fn_copy(name_tmp);
55  // done if the filename is unique (not been generated yet)
56  if(existing_names.find(atom_fn) == existing_names.end())
57  {
58  existing_names.insert(atom_fn);
59  return atom_fn;
60  }
61  }
62  }
63 
64  struct TestFile
65  {
67  u8* data; // must be delete[]-ed after comparing
68  };
69  // (must be separate array and end with NULL entry (see Filenames))
70  const char* filenames[NUM_FILES+1];
72 
74  {
75  for(size_t i = 0; i < NUM_FILES; i++)
76  {
77  const off_t size = rand(0, MAX_FILE_SIZE);
78  u8* data = new u8[size];
79 
80  // random data won't compress at all, and we want to exercise
81  // the uncompressed codepath as well => make some of the files
82  // easily compressible (much less values).
83  const bool make_easily_compressible = (rand(0, 100) > 50);
84  if(make_easily_compressible)
85  {
86  for(off_t i = 0; i < size; i++)
87  data[i] = rand() & 0x0F;
88  }
89  else
90  {
91  for(off_t i = 0; i < size; i++)
92  data[i] = rand() & 0xFF;
93  }
94 
96  files[i].size = size;
97  files[i].data = data;
98 
99  ssize_t bytes_written = vfs_store(filenames[i], data, size, FILE_NO_AIO);
100  TS_ASSERT_EQUALS(bytes_written, size);
101  }
102 
103  // 0-terminate the list - see Filenames decl.
104  filenames[NUM_FILES] = NULL;
105  }
106 
107 public:
109  : archive_fn("test_archive_random_data.zip") {}
110 
111  void setUp()
112  {
113  (void)path_SetRoot(0, ".");
114  vfs_init();
115  }
116 
117  void tearDown()
118  {
119  vfs_shutdown();
120  path_ResetRootDir();
121  }
122 
124  {
125  if(!file_exists("archivetest")) // don't get stuck if this test fails and never deletes the directory it created
126  TS_ASSERT_OK(dir_create("archivetest"));
127 
128  TS_ASSERT_OK(vfs_mount("", "archivetest"));
129 
131  TS_ASSERT_OK(archive_build(archive_fn, filenames));
132 
133  // wipe out file cache, otherwise we're just going to get back
134  // the file contents read during archive_build .
135  file_cache_reset();
136 
137  // read in each file and compare file contents
138  Handle ha = archive_open(archive_fn);
139  TS_ASSERT(ha > 0);
140  for(size_t i = 0; i < NUM_FILES; i++)
141  {
142  File f;
143  TS_ASSERT_OK(afile_open(ha, filenames[i], 0, 0, &f));
144  FileIOBuf buf = FILE_BUF_ALLOC;
145  ssize_t bytes_read = afile_read(&f, 0, files[i].size, &buf);
146  TS_ASSERT_EQUALS(bytes_read, files[i].size);
147 
148  TS_ASSERT_SAME_DATA(buf, files[i].data, files[i].size);
149 
150  TS_ASSERT_OK(file_cache_free(buf));
151  TS_ASSERT_OK(afile_close(&f));
152  SAFE_ARRAY_DELETE(files[i].data);
153  }
154  TS_ASSERT_OK(archive_close(ha));
155 
156  dir_delete("archivetest");
157  file_delete(archive_fn);
158  }
159 
161  {
162  // setUp has already vfs_init-ed it and tearDown will vfs_shutdown.
163  vfs_shutdown();
164  vfs_init();
165  }
166 };
#define u8
Definition: types.h:39
void test_create_archive_with_random_files()
const char *const archive_fn
void base32(const size_t in_len, const u8 *in, u8 *out)
generate the base32 textual representation of a buffer.
Definition: base32.cpp:31
static const size_t MAX_FILE_SIZE
const char * gen_random_name()
const char * filenames[NUM_FILES+1]
__int64 off_t
Definition: wposix_types.h:91
std::set< const char * > existing_names
i64 Handle
`handle&#39; representing a reference to a resource (sound, texture, etc.)
Definition: handle.h:41
intptr_t ssize_t
Definition: wposix_types.h:82
#define u32
Definition: types.h:41
#define SAFE_ARRAY_DELETE(p)
delete memory ensuing from new[] and set the pointer to zero (thus making double-frees safe / a no-op...
size_t rand(size_t min_inclusive, size_t max_exclusive)
return random integer in [min, max).
Definition: rand.cpp:53
static const size_t NUM_FILES
Definition: file.h:45
#define TS_ASSERT_OK(expr)
Definition: self_test.h:263
TestFile files[NUM_FILES]