test/Dictionary_test.cpp
author Jens Alfke <jens@mooseyard.com>
Thu Sep 24 10:28:50 2009 -0700 (2009-09-24)
changeset 3 8e3ae153e2c9
parent 0 31a43d94cc26
permissions -rw-r--r--
Fixed a nasty bug in HashDictionary that could cause heap corruption after removing a value. Added a test case to catch that bug. A few tweaks to Hash.
jens@0
     1
/*
jens@0
     2
 *  Dictionary_test.cpp
jens@0
     3
 *  Ottoman
jens@0
     4
 *
jens@0
     5
 *  Created by Jens Alfke on 9/4/09.
jens@0
     6
 *  Copyright 2009 Jens Alfke. All rights reserved.
jens@0
     7
 *  BSD-Licensed: See the file "LICENSE.txt" for details.
jens@0
     8
 */
jens@0
     9
jens@0
    10
jens@0
    11
#include <gtest/gtest.h>
jens@0
    12
#include "TestUtils.h"
jens@0
    13
#include "File.h"
jens@0
    14
#include "Dictionary.h"
jens@0
    15
#include "Hash.h"
jens@0
    16
#include <fcntl.h>
jens@0
    17
#include <stdio.h>
jens@0
    18
jens@0
    19
using namespace Mooseyard;
jens@0
    20
jens@0
    21
static const HashDictionary& getDict() {
jens@0
    22
    static HashDictionary *sDict;
jens@0
    23
    if (!sDict) {
jens@0
    24
        printf("Building large HashDictionary...\n");
jens@0
    25
        sDict = new HashDictionary();
jens@0
    26
        readWords();
jens@0
    27
        for( int i=0; i<sNWords; i++) {
jens@0
    28
            Blob kv(sWords[i]);
jens@0
    29
            sDict->put(Key(kv),kv);
jens@0
    30
        }
jens@0
    31
    }
jens@0
    32
    return *sDict;
jens@0
    33
}
jens@0
    34
jens@3
    35
TEST(Dictionary,AddRemove) {
jens@3
    36
    HashDictionary dict;
jens@3
    37
    EXPECT_EQ(0, dict.count());
jens@3
    38
    dict.put("key 1", "value 1");
jens@3
    39
    EXPECT_EQ(1, dict.count());
jens@3
    40
    dict.put("key 2", "value 2");
jens@3
    41
    EXPECT_EQ(2, dict.count());
jens@3
    42
    dict.put("key 3", "value 3");
jens@3
    43
    EXPECT_TRUE(dict.get("key 1").equals("value 1"));
jens@3
    44
    EXPECT_TRUE(dict.get("key 2").equals("value 2"));
jens@3
    45
    EXPECT_TRUE(dict.get("key 3").equals("value 3"));
jens@3
    46
    EXPECT_TRUE(!dict.get("key 4"));
jens@3
    47
jens@3
    48
    EXPECT_TRUE(dict.remove("key 2"));
jens@3
    49
    EXPECT_EQ(2, dict.count());
jens@3
    50
    EXPECT_TRUE(dict.get("key 1").equals("value 1"));
jens@3
    51
    EXPECT_TRUE(!dict.get("key 2"));
jens@3
    52
    EXPECT_TRUE(dict.get("key 3").equals("value 3"));
jens@3
    53
}
jens@3
    54
jens@0
    55
TEST(Dictionary,GetAll) {
jens@0
    56
    const Dictionary &dict = getDict();
jens@0
    57
    EXPECT_EQ( sNWords ,  dict.count() );
jens@0
    58
    for( int i=0; i<sNWords; i++) {
jens@0
    59
        Key key(sWords[i]);
jens@0
    60
        Blob value = dict.get(key);
jens@0
    61
        EXPECT_TRUE(value);
jens@0
    62
        EXPECT_TRUE( value.equals(key) );
jens@0
    63
    }
jens@0
    64
}
jens@0
    65
jens@0
    66
TEST(Dictionary,Iterate) {
jens@0
    67
    const HashDictionary &dict = getDict();
jens@0
    68
    Timer t("Iterating Dictionary", sNWords);
jens@0
    69
    int n=0;
jens@0
    70
    for( HashDictionary::Iterator it(dict); it; ++it) {
jens@0
    71
        n++;
jens@0
    72
        EXPECT_TRUE(it.key().length > 0 && it.key().length < 50);
jens@0
    73
        EXPECT_TRUE(it.key().equals(it.value()));
jens@0
    74
        EXPECT_EQ( 0, ((size_t)it.value().bytes & 0x3) );  // 4-byte aligned
jens@0
    75
    }
jens@0
    76
    EXPECT_EQ(sNWords, n);
jens@0
    77
}
jens@0
    78
jens@0
    79
TEST(Dictionary,Overlay) {
jens@0
    80
    const Dictionary &dict = getDict();
jens@0
    81
    OverlayDictionary overlay(&dict);
jens@0
    82
    
jens@0
    83
    EXPECT_EQ( sNWords ,  overlay.count() );
jens@0
    84
    EXPECT_TRUE(overlay.get("animal").equals("animal"));
jens@0
    85
    EXPECT_TRUE(overlay.get("asparagus").equals("asparagus"));
jens@0
    86
    EXPECT_FALSE(overlay.get("growf"));
jens@0
    87
    
jens@0
    88
    overlay.put("animal", "AMINAL");
jens@0
    89
    overlay.put("growf", "growf");
jens@0
    90
    EXPECT_TRUE(overlay.remove("asparagus"));
jens@0
    91
    
jens@0
    92
    EXPECT_EQ( sNWords, overlay.count() );
jens@0
    93
    EXPECT_TRUE(overlay.get("animal").equals("AMINAL"));
jens@0
    94
    EXPECT_TRUE(overlay.get("growf").equals("growf"));
jens@0
    95
    EXPECT_TRUE(overlay.contains("growf"));
jens@0
    96
    EXPECT_FALSE(overlay.get("asparagus"));
jens@0
    97
    EXPECT_FALSE(overlay.contains("asparagus"));
jens@0
    98
    
jens@0
    99
    int n=0;
jens@0
   100
    for( OverlayDictionary::Iterator it(overlay); it; ++it) {
jens@0
   101
        n++;
jens@0
   102
        EXPECT_TRUE(!it.key().equals("asparagus"));
jens@0
   103
    }
jens@0
   104
    EXPECT_EQ(sNWords, n);
jens@0
   105
    
jens@0
   106
    printf("Testing ChangeIterator...\n");
jens@0
   107
    n=0;
jens@0
   108
    int foundAsparagus=0, foundAnimal=0, foundGrowf=0;
jens@0
   109
    for( Dictionary::ChangeIterator it(&overlay); it; ++it) {
jens@0
   110
        n++;
jens@0
   111
        if (it.key().equals("animal")) {
jens@0
   112
            foundAnimal++;
jens@0
   113
            EXPECT_TRUE(it.value().equals("AMINAL"));
jens@0
   114
            EXPECT_TRUE(it.otherValue().equals("animal"));
jens@0
   115
        } else if (it.key().equals("asparagus")) {
jens@0
   116
            foundAsparagus++;
jens@0
   117
            EXPECT_FALSE(it.value());
jens@0
   118
            EXPECT_TRUE(it.otherValue().equals("asparagus"));
jens@0
   119
        } else if (it.key().equals("growf")) {
jens@0
   120
            foundGrowf++;
jens@0
   121
            EXPECT_TRUE(it.value().equals("growf"));
jens@0
   122
            EXPECT_FALSE(it.otherValue());
jens@0
   123
        } else {
jens@0
   124
            EXPECT_TRUE(false);
jens@0
   125
        }
jens@0
   126
    }
jens@0
   127
    EXPECT_EQ(1, foundAnimal);
jens@0
   128
    EXPECT_EQ(1, foundAsparagus);
jens@0
   129
    EXPECT_EQ(1, foundGrowf);
jens@0
   130
    EXPECT_EQ(3, n);
jens@0
   131
}