test/VersionDictionary_test.cpp
author Jens Alfke <jens@mooseyard.com>
Sun Sep 20 15:14:12 2009 -0700 (2009-09-20)
changeset 0 31a43d94cc26
child 8 21a6c17f4e3e
permissions -rw-r--r--
First official checkin.
     1 /*
     2  *  VersionDictionary_test.cpp
     3  *  Ottoman
     4  *
     5  *  Created by Jens Alfke on 9/2/09.
     6  *  Copyright 2009 Jens Alfke. All rights reserved.
     7  *  BSD-Licensed: See the file "LICENSE.txt" for details.
     8  */
     9 
    10 
    11 #define VERSIONDICTIONARY_TESTING 1
    12 
    13 #include <gtest/gtest.h>
    14 #include "TestUtils.h"
    15 #include "Chunk.h"
    16 #include "File.h"
    17 #include "VersionDictionary.h"
    18 #include "Hash.h"
    19 #include <fcntl.h>
    20 #include <stdio.h>
    21 
    22 using namespace Mooseyard;
    23 
    24 
    25 class OverlayVersionDictionary :public OverlayDictionary {
    26 public:
    27     OverlayVersionDictionary (File *file)
    28     :OverlayDictionary(new VersionDictionary(file))
    29     { }  
    30     
    31     int generation() const                  {return ((VersionDictionary*)base())->generation();}
    32     time_t timestamp() const                {return ((VersionDictionary*)base())->timestamp();}
    33 
    34     void save(){
    35         saveAs(((VersionDictionary*)base())->file());
    36     }
    37     
    38     void saveAs (File *dstFile) {
    39         VersionDictionary* oldBase = (VersionDictionary*) base();
    40         revertTo( ((VersionDictionary*)base())->_appendAndOpen(overlay(), dstFile, baseReplaced()) );
    41         delete oldBase;
    42     }
    43 };
    44 
    45 
    46 
    47 TEST(File,HasPath) {
    48     {
    49         File f("/tmp/jubba", O_RDWR | O_CREAT | O_TRUNC);
    50         f.write("howdy");
    51     }
    52     {
    53         File f("/tmp/jubba", O_RDWR);
    54         EXPECT_TRUE(f.hasPath("/tmp/jubba"));
    55         File::unlink("/tmp/jubba");
    56         EXPECT_FALSE(f.hasPath("/tmp/jubba"));
    57         
    58         File f2("/tmp/jubba", O_RDWR | O_CREAT | O_TRUNC);
    59         f2.write("howdy");
    60         f2.flush();
    61 
    62         EXPECT_FALSE(f.hasPath("/tmp/jubba"));
    63         EXPECT_TRUE(f2.hasPath("/tmp/jubba"));
    64     }
    65     File::unlink("/tmp/jubba");
    66 }
    67 
    68 
    69 static int TestIterate (File *file) {
    70     printf("Iterating the chunks...\n");
    71     int lastType = -1;
    72     int count = 0;
    73     int n = 0;
    74     ChunkIterator it(file, 4);
    75     for (; it; ++it) {
    76         uint16_t type = it.chunk()->type();
    77         if (type != lastType) {
    78             if (count > 0)
    79                 printf("%6d\n", count);
    80             printf("type %u ... ", type);
    81             lastType = type;
    82             count = 0;
    83         }
    84         count++;
    85         EXPECT_LE(type, 3);
    86         if (type != 0)      // don't count padding chunks
    87             n++;
    88     }
    89     if (count > 0)
    90         printf("%6d\n", count);
    91     EXPECT_TRUE(it.atEOF());
    92     return n;
    93 }    
    94 
    95 
    96 static void TestWithWords (const int nWords) {
    97     ASSERT_EQ(8, sizeof(Chunk));
    98     ASSERT_EQ(8, sizeof(KeyValueChunk));
    99     
   100     printf("Building dictionary of %i words...\n", nWords);
   101     readWords();
   102     HashDictionary dict;
   103     for( int i=0; i<nWords; i++) {
   104         Blob kv(sWords[i]);
   105         dict.put(Key(kv),kv);
   106     }
   107     
   108     time_t startTime = ::time(NULL);
   109     time_t createTime;
   110     {
   111         File file("/tmp/hashfiletest", O_RDWR | O_CREAT | O_TRUNC);
   112         VersionDictionary *hf;
   113         {
   114             Timer t("Creating & writing VersionDictionary", nWords);
   115             file.write("Ha5h", 4);     // VersionDictionary won't write to an empty file
   116             hf = VersionDictionary::create(&file, &dict);
   117         }
   118         printf("File size: %llu bytes\n", file.length());
   119         ASSERT_TRUE(hf!=NULL);
   120         ASSERT_EQ(0, hf->generation());
   121         createTime = hf->timestamp();
   122         ASSERT_GE(createTime, startTime);
   123         ASSERT_LE(createTime, ::time(NULL));
   124         delete hf;
   125     }
   126     {
   127         File file("/tmp/hashfiletest");
   128         VersionDictionary hf(&file);
   129         ASSERT_EQ(0, hf.generation());
   130         ASSERT_EQ(createTime, hf.timestamp());
   131         {
   132             Timer t("Reading from VersionDictionary", nWords);
   133             EXPECT_EQ( nWords ,  hf.count() );
   134             for( int i=0; i<nWords; i++) {
   135                 Key key(sWords[i]);
   136                 Blob value = hf.get(key);
   137                 ASSERT_TRUE(value);
   138                 ASSERT_TRUE( value.equals(key) ) << "expected '" << key << "', got '" << value << "' (i=" << i <<")";
   139             }
   140         }
   141         
   142         printf("Iterating through the VersionDictionary...\n");
   143         Timer t("Iterating VersionDictionary", nWords);
   144         int n=0;
   145         for( VersionDictionary::Iterator it(&hf); it; ++it) {
   146             n++;
   147             ASSERT_TRUE(it.key().length > 0 && it.key().length < 50);
   148             ASSERT_TRUE(it.key().equals(it.value()));
   149             ASSERT_EQ( 0, ((size_t)it.value().bytes & 0x3) );  // 4-byte aligned
   150         }
   151         ASSERT_EQ(nWords, n);
   152     }
   153     {
   154         printf("Opening OverlayVersionDictionary...\n");
   155         File file("/tmp/hashfiletest", O_RDWR);
   156         OverlayVersionDictionary hf(&file);
   157         EXPECT_EQ( nWords ,  hf.count() );
   158         EXPECT_TRUE(hf.get("abatement").equals("abatement"));
   159         
   160         hf.put("abaser", "DEBASER");
   161         hf.put("growf", "growf");
   162         EXPECT_TRUE(hf.remove("abatement"));
   163         
   164         EXPECT_EQ( nWords, hf.count() );
   165         EXPECT_TRUE(hf.get("abaser").equals("DEBASER"));
   166         EXPECT_TRUE(hf.get("growf").equals("growf"));
   167         EXPECT_EQ( NULL, hf.get("abatement").bytes );
   168         EXPECT_TRUE(!hf.contains("abatement"));
   169         
   170         int n=0;
   171         for( OverlayVersionDictionary::Iterator it(hf); it; ++it) {
   172             n++;
   173             ASSERT_TRUE(!it.key().equals("abatement"));
   174         }
   175         ASSERT_EQ(nWords, n);
   176         
   177         printf("Saving OverlayVersionDictionary...\n");
   178         {
   179             Timer t("Saving OverlayVersionDictionary");
   180             hf.save();
   181         }
   182         printf("File size: %llu bytes\n", file.length());
   183         
   184         EXPECT_EQ( nWords, hf.count() );
   185         EXPECT_TRUE(hf.get("abaser").equals("DEBASER"));
   186         EXPECT_TRUE(hf.get("growf").equals("growf"));
   187         EXPECT_EQ( NULL, hf.get("abatement").bytes );
   188         EXPECT_TRUE(!hf.contains("abatement"));
   189         
   190         n=0;
   191         for( OverlayVersionDictionary::Iterator it(hf); it; ++it) {
   192             n++;
   193             ASSERT_TRUE(!it.key().equals("abatement"));
   194         }
   195         ASSERT_EQ(nWords, n);
   196     }
   197     {
   198         printf("Re-opening OverlayVersionDictionary...\n");
   199         File file("/tmp/hashfiletest");
   200         OverlayVersionDictionary hf(&file);
   201         
   202         ASSERT_EQ(1, hf.generation());
   203         ASSERT_GE(hf.timestamp(), createTime);
   204         ASSERT_LE(hf.timestamp(), ::time(NULL));
   205         EXPECT_EQ( nWords ,  hf.count() );
   206         EXPECT_TRUE(hf.get("abaser").equals("DEBASER"));
   207         EXPECT_TRUE(hf.get("growf").equals("growf"));
   208         EXPECT_EQ( NULL, hf.get("abatement").bytes );
   209         EXPECT_TRUE(!hf.contains("abatement"));
   210         
   211         int n=0;
   212         for( OverlayVersionDictionary::Iterator it(hf); it; ++it) {
   213             n++;
   214             ASSERT_TRUE(!it.key().equals("abatement"));
   215         }
   216         ASSERT_EQ(nWords, n);
   217 
   218         n = TestIterate(&file);
   219         EXPECT_GE(n, nWords+1+4);
   220         if (nWords > 1000)
   221             EXPECT_GE(n, nWords+256+4);
   222     }
   223     {
   224         printf("Writing VersionDictionary to a new file...\n");
   225         File oldFile("/tmp/hashfiletest");
   226         OverlayVersionDictionary oldhf(&oldFile);
   227         
   228         File newFile("/tmp/hashfiletest2", O_RDWR | O_CREAT | O_TRUNC);
   229         newFile.write("Ha5h", 4);     // VersionDictionary won't write to an empty file
   230         oldhf.saveAs(&newFile);
   231         printf("File size: %llu bytes\n", newFile.length());
   232     }
   233     {
   234         printf("Opening new file...\n");
   235         File file("/tmp/hashfiletest2");
   236         OverlayVersionDictionary hf(&file);
   237         
   238         EXPECT_EQ( nWords ,  hf.count() );
   239         EXPECT_TRUE(hf.get("abaser").equals("DEBASER"));
   240         EXPECT_TRUE(hf.get("growf").equals("growf"));
   241         EXPECT_EQ( NULL, hf.get("abatement").bytes );
   242         EXPECT_TRUE(!hf.contains("abatement"));
   243         
   244         int n=0;
   245         for( OverlayVersionDictionary::Iterator it(hf); it; ++it) {
   246             n++;
   247             ASSERT_TRUE(!it.key().equals("abatement"));
   248         }
   249         ASSERT_EQ(nWords, n);
   250         
   251         n = TestIterate(&file);
   252         EXPECT_GE(n, nWords+1+1);
   253         if (nWords > 1000)
   254             EXPECT_EQ(nWords+256+1, n);
   255     }
   256 }    
   257 
   258 
   259 TEST(VersionDictionary,BuildSmall) {
   260     TestWithWords(100);
   261 }
   262 
   263 TEST(VersionDictionary,BuildLarge) {
   264     TestWithWords(sNWords);
   265 }