1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/test/VersionDictionary_test.cpp Sun Sep 20 15:14:12 2009 -0700
1.3 @@ -0,0 +1,265 @@
1.4 +/*
1.5 + * VersionDictionary_test.cpp
1.6 + * Ottoman
1.7 + *
1.8 + * Created by Jens Alfke on 9/2/09.
1.9 + * Copyright 2009 Jens Alfke. All rights reserved.
1.10 + * BSD-Licensed: See the file "LICENSE.txt" for details.
1.11 + */
1.12 +
1.13 +
1.14 +#define VERSIONDICTIONARY_TESTING 1
1.15 +
1.16 +#include <gtest/gtest.h>
1.17 +#include "TestUtils.h"
1.18 +#include "Chunk.h"
1.19 +#include "File.h"
1.20 +#include "VersionDictionary.h"
1.21 +#include "Hash.h"
1.22 +#include <fcntl.h>
1.23 +#include <stdio.h>
1.24 +
1.25 +using namespace Mooseyard;
1.26 +
1.27 +
1.28 +class OverlayVersionDictionary :public OverlayDictionary {
1.29 +public:
1.30 + OverlayVersionDictionary (File *file)
1.31 + :OverlayDictionary(new VersionDictionary(file))
1.32 + { }
1.33 +
1.34 + int generation() const {return ((VersionDictionary*)base())->generation();}
1.35 + time_t timestamp() const {return ((VersionDictionary*)base())->timestamp();}
1.36 +
1.37 + void save(){
1.38 + saveAs(((VersionDictionary*)base())->file());
1.39 + }
1.40 +
1.41 + void saveAs (File *dstFile) {
1.42 + VersionDictionary* oldBase = (VersionDictionary*) base();
1.43 + revertTo( ((VersionDictionary*)base())->_appendAndOpen(overlay(), dstFile, baseReplaced()) );
1.44 + delete oldBase;
1.45 + }
1.46 +};
1.47 +
1.48 +
1.49 +
1.50 +TEST(File,HasPath) {
1.51 + {
1.52 + File f("/tmp/jubba", O_RDWR | O_CREAT | O_TRUNC);
1.53 + f.write("howdy");
1.54 + }
1.55 + {
1.56 + File f("/tmp/jubba", O_RDWR);
1.57 + EXPECT_TRUE(f.hasPath("/tmp/jubba"));
1.58 + File::unlink("/tmp/jubba");
1.59 + EXPECT_FALSE(f.hasPath("/tmp/jubba"));
1.60 +
1.61 + File f2("/tmp/jubba", O_RDWR | O_CREAT | O_TRUNC);
1.62 + f2.write("howdy");
1.63 + f2.flush();
1.64 +
1.65 + EXPECT_FALSE(f.hasPath("/tmp/jubba"));
1.66 + EXPECT_TRUE(f2.hasPath("/tmp/jubba"));
1.67 + }
1.68 + File::unlink("/tmp/jubba");
1.69 +}
1.70 +
1.71 +
1.72 +static int TestIterate (File *file) {
1.73 + printf("Iterating the chunks...\n");
1.74 + int lastType = -1;
1.75 + int count = 0;
1.76 + int n = 0;
1.77 + ChunkIterator it(file, 4);
1.78 + for (; it; ++it) {
1.79 + uint16_t type = it.chunk()->type();
1.80 + if (type != lastType) {
1.81 + if (count > 0)
1.82 + printf("%6d\n", count);
1.83 + printf("type %u ... ", type);
1.84 + lastType = type;
1.85 + count = 0;
1.86 + }
1.87 + count++;
1.88 + EXPECT_LE(type, 3);
1.89 + if (type != 0) // don't count padding chunks
1.90 + n++;
1.91 + }
1.92 + if (count > 0)
1.93 + printf("%6d\n", count);
1.94 + EXPECT_TRUE(it.atEOF());
1.95 + return n;
1.96 +}
1.97 +
1.98 +
1.99 +static void TestWithWords (const int nWords) {
1.100 + ASSERT_EQ(8, sizeof(Chunk));
1.101 + ASSERT_EQ(8, sizeof(KeyValueChunk));
1.102 +
1.103 + printf("Building dictionary of %i words...\n", nWords);
1.104 + readWords();
1.105 + HashDictionary dict;
1.106 + for( int i=0; i<nWords; i++) {
1.107 + Blob kv(sWords[i]);
1.108 + dict.put(Key(kv),kv);
1.109 + }
1.110 +
1.111 + time_t startTime = ::time(NULL);
1.112 + time_t createTime;
1.113 + {
1.114 + File file("/tmp/hashfiletest", O_RDWR | O_CREAT | O_TRUNC);
1.115 + VersionDictionary *hf;
1.116 + {
1.117 + Timer t("Creating & writing VersionDictionary", nWords);
1.118 + file.write("Ha5h", 4); // VersionDictionary won't write to an empty file
1.119 + hf = VersionDictionary::create(&file, &dict);
1.120 + }
1.121 + printf("File size: %llu bytes\n", file.length());
1.122 + ASSERT_TRUE(hf!=NULL);
1.123 + ASSERT_EQ(0, hf->generation());
1.124 + createTime = hf->timestamp();
1.125 + ASSERT_GE(createTime, startTime);
1.126 + ASSERT_LE(createTime, ::time(NULL));
1.127 + delete hf;
1.128 + }
1.129 + {
1.130 + File file("/tmp/hashfiletest");
1.131 + VersionDictionary hf(&file);
1.132 + ASSERT_EQ(0, hf.generation());
1.133 + ASSERT_EQ(createTime, hf.timestamp());
1.134 + {
1.135 + Timer t("Reading from VersionDictionary", nWords);
1.136 + EXPECT_EQ( nWords , hf.count() );
1.137 + for( int i=0; i<nWords; i++) {
1.138 + Key key(sWords[i]);
1.139 + Blob value = hf.get(key);
1.140 + ASSERT_TRUE(value);
1.141 + ASSERT_TRUE( value.equals(key) ) << "expected '" << key << "', got '" << value << "' (i=" << i <<")";
1.142 + }
1.143 + }
1.144 +
1.145 + printf("Iterating through the VersionDictionary...\n");
1.146 + Timer t("Iterating VersionDictionary", nWords);
1.147 + int n=0;
1.148 + for( VersionDictionary::Iterator it(&hf); it; ++it) {
1.149 + n++;
1.150 + ASSERT_TRUE(it.key().length > 0 && it.key().length < 50);
1.151 + ASSERT_TRUE(it.key().equals(it.value()));
1.152 + ASSERT_EQ( 0, ((size_t)it.value().bytes & 0x3) ); // 4-byte aligned
1.153 + }
1.154 + ASSERT_EQ(nWords, n);
1.155 + }
1.156 + {
1.157 + printf("Opening OverlayVersionDictionary...\n");
1.158 + File file("/tmp/hashfiletest", O_RDWR);
1.159 + OverlayVersionDictionary hf(&file);
1.160 + EXPECT_EQ( nWords , hf.count() );
1.161 + EXPECT_TRUE(hf.get("abatement").equals("abatement"));
1.162 +
1.163 + hf.put("abaser", "DEBASER");
1.164 + hf.put("growf", "growf");
1.165 + EXPECT_TRUE(hf.remove("abatement"));
1.166 +
1.167 + EXPECT_EQ( nWords, hf.count() );
1.168 + EXPECT_TRUE(hf.get("abaser").equals("DEBASER"));
1.169 + EXPECT_TRUE(hf.get("growf").equals("growf"));
1.170 + EXPECT_EQ( NULL, hf.get("abatement").bytes );
1.171 + EXPECT_TRUE(!hf.contains("abatement"));
1.172 +
1.173 + int n=0;
1.174 + for( OverlayVersionDictionary::Iterator it(hf); it; ++it) {
1.175 + n++;
1.176 + ASSERT_TRUE(!it.key().equals("abatement"));
1.177 + }
1.178 + ASSERT_EQ(nWords, n);
1.179 +
1.180 + printf("Saving OverlayVersionDictionary...\n");
1.181 + {
1.182 + Timer t("Saving OverlayVersionDictionary");
1.183 + hf.save();
1.184 + }
1.185 + printf("File size: %llu bytes\n", file.length());
1.186 +
1.187 + EXPECT_EQ( nWords, hf.count() );
1.188 + EXPECT_TRUE(hf.get("abaser").equals("DEBASER"));
1.189 + EXPECT_TRUE(hf.get("growf").equals("growf"));
1.190 + EXPECT_EQ( NULL, hf.get("abatement").bytes );
1.191 + EXPECT_TRUE(!hf.contains("abatement"));
1.192 +
1.193 + n=0;
1.194 + for( OverlayVersionDictionary::Iterator it(hf); it; ++it) {
1.195 + n++;
1.196 + ASSERT_TRUE(!it.key().equals("abatement"));
1.197 + }
1.198 + ASSERT_EQ(nWords, n);
1.199 + }
1.200 + {
1.201 + printf("Re-opening OverlayVersionDictionary...\n");
1.202 + File file("/tmp/hashfiletest");
1.203 + OverlayVersionDictionary hf(&file);
1.204 +
1.205 + ASSERT_EQ(1, hf.generation());
1.206 + ASSERT_GE(hf.timestamp(), createTime);
1.207 + ASSERT_LE(hf.timestamp(), ::time(NULL));
1.208 + EXPECT_EQ( nWords , hf.count() );
1.209 + EXPECT_TRUE(hf.get("abaser").equals("DEBASER"));
1.210 + EXPECT_TRUE(hf.get("growf").equals("growf"));
1.211 + EXPECT_EQ( NULL, hf.get("abatement").bytes );
1.212 + EXPECT_TRUE(!hf.contains("abatement"));
1.213 +
1.214 + int n=0;
1.215 + for( OverlayVersionDictionary::Iterator it(hf); it; ++it) {
1.216 + n++;
1.217 + ASSERT_TRUE(!it.key().equals("abatement"));
1.218 + }
1.219 + ASSERT_EQ(nWords, n);
1.220 +
1.221 + n = TestIterate(&file);
1.222 + EXPECT_GE(n, nWords+1+4);
1.223 + if (nWords > 1000)
1.224 + EXPECT_GE(n, nWords+256+4);
1.225 + }
1.226 + {
1.227 + printf("Writing VersionDictionary to a new file...\n");
1.228 + File oldFile("/tmp/hashfiletest");
1.229 + OverlayVersionDictionary oldhf(&oldFile);
1.230 +
1.231 + File newFile("/tmp/hashfiletest2", O_RDWR | O_CREAT | O_TRUNC);
1.232 + newFile.write("Ha5h", 4); // VersionDictionary won't write to an empty file
1.233 + oldhf.saveAs(&newFile);
1.234 + printf("File size: %llu bytes\n", newFile.length());
1.235 + }
1.236 + {
1.237 + printf("Opening new file...\n");
1.238 + File file("/tmp/hashfiletest2");
1.239 + OverlayVersionDictionary hf(&file);
1.240 +
1.241 + EXPECT_EQ( nWords , hf.count() );
1.242 + EXPECT_TRUE(hf.get("abaser").equals("DEBASER"));
1.243 + EXPECT_TRUE(hf.get("growf").equals("growf"));
1.244 + EXPECT_EQ( NULL, hf.get("abatement").bytes );
1.245 + EXPECT_TRUE(!hf.contains("abatement"));
1.246 +
1.247 + int n=0;
1.248 + for( OverlayVersionDictionary::Iterator it(hf); it; ++it) {
1.249 + n++;
1.250 + ASSERT_TRUE(!it.key().equals("abatement"));
1.251 + }
1.252 + ASSERT_EQ(nWords, n);
1.253 +
1.254 + n = TestIterate(&file);
1.255 + EXPECT_GE(n, nWords+1+1);
1.256 + if (nWords > 1000)
1.257 + EXPECT_EQ(nWords+256+1, n);
1.258 + }
1.259 +}
1.260 +
1.261 +
1.262 +TEST(VersionDictionary,BuildSmall) {
1.263 + TestWithWords(100);
1.264 +}
1.265 +
1.266 +TEST(VersionDictionary,BuildLarge) {
1.267 + TestWithWords(sNWords);
1.268 +}