Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | // Copyright (c) 2008, Google Inc. |
michael@0 | 2 | // All rights reserved. |
michael@0 | 3 | // |
michael@0 | 4 | // Redistribution and use in source and binary forms, with or without |
michael@0 | 5 | // modification, are permitted provided that the following conditions are |
michael@0 | 6 | // met: |
michael@0 | 7 | // |
michael@0 | 8 | // * Redistributions of source code must retain the above copyright |
michael@0 | 9 | // notice, this list of conditions and the following disclaimer. |
michael@0 | 10 | // * Redistributions in binary form must reproduce the above |
michael@0 | 11 | // copyright notice, this list of conditions and the following disclaimer |
michael@0 | 12 | // in the documentation and/or other materials provided with the |
michael@0 | 13 | // distribution. |
michael@0 | 14 | // * Neither the name of Google Inc. nor the names of its |
michael@0 | 15 | // contributors may be used to endorse or promote products derived from |
michael@0 | 16 | // this software without specific prior written permission. |
michael@0 | 17 | // |
michael@0 | 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
michael@0 | 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@0 | 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@0 | 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
michael@0 | 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
michael@0 | 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
michael@0 | 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
michael@0 | 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 29 | |
michael@0 | 30 | #import "SimpleStringDictionaryTest.h" |
michael@0 | 31 | #import "SimpleStringDictionary.h" |
michael@0 | 32 | |
michael@0 | 33 | using google_breakpad::KeyValueEntry; |
michael@0 | 34 | using google_breakpad::SimpleStringDictionary; |
michael@0 | 35 | using google_breakpad::SimpleStringDictionaryIterator; |
michael@0 | 36 | |
michael@0 | 37 | @implementation SimpleStringDictionaryTest |
michael@0 | 38 | |
michael@0 | 39 | //============================================================================== |
michael@0 | 40 | - (void)testKeyValueEntry { |
michael@0 | 41 | KeyValueEntry entry; |
michael@0 | 42 | |
michael@0 | 43 | // Verify that initial state is correct |
michael@0 | 44 | STAssertFalse(entry.IsActive(), @"Initial key value entry is active!"); |
michael@0 | 45 | STAssertEquals(strlen(entry.GetKey()), (size_t)0, @"Empty key value did not " |
michael@0 | 46 | @"have length 0"); |
michael@0 | 47 | STAssertEquals(strlen(entry.GetValue()), (size_t)0, @"Empty key value did not " |
michael@0 | 48 | @"have length 0"); |
michael@0 | 49 | |
michael@0 | 50 | // Try setting a key/value and then verify |
michael@0 | 51 | entry.SetKeyValue("key1", "value1"); |
michael@0 | 52 | STAssertEqualCStrings(entry.GetKey(), "key1", @"key was not equal to key1"); |
michael@0 | 53 | STAssertEqualCStrings(entry.GetValue(), "value1", @"value was not equal"); |
michael@0 | 54 | |
michael@0 | 55 | // Try setting a new value |
michael@0 | 56 | entry.SetValue("value3"); |
michael@0 | 57 | |
michael@0 | 58 | // Make sure the new value took |
michael@0 | 59 | STAssertEqualCStrings(entry.GetValue(), "value3", @"value was not equal"); |
michael@0 | 60 | |
michael@0 | 61 | // Make sure the key didn't change |
michael@0 | 62 | STAssertEqualCStrings(entry.GetKey(), "key1", @"key changed after setting " |
michael@0 | 63 | @"value!"); |
michael@0 | 64 | |
michael@0 | 65 | // Try setting a new key/value and then verify |
michael@0 | 66 | entry.SetKeyValue("key2", "value2"); |
michael@0 | 67 | STAssertEqualCStrings(entry.GetKey(), "key2", @"New key was not equal to " |
michael@0 | 68 | @"key2"); |
michael@0 | 69 | STAssertEqualCStrings(entry.GetValue(), "value2", @"New value was not equal " |
michael@0 | 70 | @"to value2"); |
michael@0 | 71 | |
michael@0 | 72 | // Clear the entry and verify the key and value are empty strings |
michael@0 | 73 | entry.Clear(); |
michael@0 | 74 | STAssertFalse(entry.IsActive(), @"Key value clear did not clear object"); |
michael@0 | 75 | STAssertEquals(strlen(entry.GetKey()), (size_t)0, @"Length of cleared key " |
michael@0 | 76 | @"was not 0"); |
michael@0 | 77 | STAssertEquals(strlen(entry.GetValue()), (size_t)0, @"Length of cleared " |
michael@0 | 78 | @"value was not 0!"); |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | - (void)testEmptyKeyValueCombos { |
michael@0 | 82 | KeyValueEntry entry; |
michael@0 | 83 | entry.SetKeyValue(NULL, NULL); |
michael@0 | 84 | STAssertEqualCStrings(entry.GetKey(), "", @"Setting NULL key did not return " |
michael@0 | 85 | @"empty key!"); |
michael@0 | 86 | STAssertEqualCStrings(entry.GetValue(), "", @"Setting NULL value did not " |
michael@0 | 87 | @"set empty string value!"); |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | |
michael@0 | 91 | //============================================================================== |
michael@0 | 92 | - (void)testSimpleStringDictionary { |
michael@0 | 93 | // Make a new dictionary |
michael@0 | 94 | SimpleStringDictionary *dict = new SimpleStringDictionary(); |
michael@0 | 95 | STAssertTrue(dict != NULL, nil); |
michael@0 | 96 | |
michael@0 | 97 | // try passing in NULL for key |
michael@0 | 98 | //dict->SetKeyValue(NULL, "bad"); // causes assert() to fire |
michael@0 | 99 | |
michael@0 | 100 | // Set three distinct values on three keys |
michael@0 | 101 | dict->SetKeyValue("key1", "value1"); |
michael@0 | 102 | dict->SetKeyValue("key2", "value2"); |
michael@0 | 103 | dict->SetKeyValue("key3", "value3"); |
michael@0 | 104 | |
michael@0 | 105 | STAssertTrue(!strcmp(dict->GetValueForKey("key1"), "value1"), nil); |
michael@0 | 106 | STAssertTrue(!strcmp(dict->GetValueForKey("key2"), "value2"), nil); |
michael@0 | 107 | STAssertTrue(!strcmp(dict->GetValueForKey("key3"), "value3"), nil); |
michael@0 | 108 | STAssertEquals(dict->GetCount(), 3, @"GetCount did not return 3"); |
michael@0 | 109 | // try an unknown key |
michael@0 | 110 | STAssertTrue(dict->GetValueForKey("key4") == NULL, nil); |
michael@0 | 111 | |
michael@0 | 112 | // try a NULL key |
michael@0 | 113 | //STAssertTrue(dict->GetValueForKey(NULL) == NULL, nil); // asserts |
michael@0 | 114 | |
michael@0 | 115 | // Remove a key |
michael@0 | 116 | dict->RemoveKey("key3"); |
michael@0 | 117 | |
michael@0 | 118 | // Now make sure it's not there anymore |
michael@0 | 119 | STAssertTrue(dict->GetValueForKey("key3") == NULL, nil); |
michael@0 | 120 | |
michael@0 | 121 | // Remove a NULL key |
michael@0 | 122 | //dict->RemoveKey(NULL); // will cause assert() to fire |
michael@0 | 123 | |
michael@0 | 124 | // Remove by setting value to NULL |
michael@0 | 125 | dict->SetKeyValue("key2", NULL); |
michael@0 | 126 | |
michael@0 | 127 | // Now make sure it's not there anymore |
michael@0 | 128 | STAssertTrue(dict->GetValueForKey("key2") == NULL, nil); |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | //============================================================================== |
michael@0 | 132 | // The idea behind this test is to add a bunch of values to the dictionary, |
michael@0 | 133 | // remove some in the middle, then add a few more in. We then create a |
michael@0 | 134 | // SimpleStringDictionaryIterator and iterate through the dictionary, taking |
michael@0 | 135 | // note of the key/value pairs we see. We then verify that it iterates |
michael@0 | 136 | // through exactly the number of key/value pairs we expect, and that they |
michael@0 | 137 | // match one-for-one with what we would expect. In all cases we're setting |
michael@0 | 138 | // key value pairs of the form: |
michael@0 | 139 | // |
michael@0 | 140 | // key<n>/value<n> (like key0/value0, key17,value17, etc.) |
michael@0 | 141 | // |
michael@0 | 142 | - (void)testSimpleStringDictionaryIterator { |
michael@0 | 143 | SimpleStringDictionary *dict = new SimpleStringDictionary(); |
michael@0 | 144 | STAssertTrue(dict != NULL, nil); |
michael@0 | 145 | |
michael@0 | 146 | char key[KeyValueEntry::MAX_STRING_STORAGE_SIZE]; |
michael@0 | 147 | char value[KeyValueEntry::MAX_STRING_STORAGE_SIZE]; |
michael@0 | 148 | |
michael@0 | 149 | const int kDictionaryCapacity = SimpleStringDictionary::MAX_NUM_ENTRIES; |
michael@0 | 150 | const int kPartitionIndex = kDictionaryCapacity - 5; |
michael@0 | 151 | |
michael@0 | 152 | // We assume at least this size in the tests below |
michael@0 | 153 | STAssertTrue(kDictionaryCapacity >= 64, nil); |
michael@0 | 154 | |
michael@0 | 155 | // We'll keep track of the number of key/value pairs we think should |
michael@0 | 156 | // be in the dictionary |
michael@0 | 157 | int expectedDictionarySize = 0; |
michael@0 | 158 | |
michael@0 | 159 | // Set a bunch of key/value pairs like key0/value0, key1/value1, ... |
michael@0 | 160 | for (int i = 0; i < kPartitionIndex; ++i) { |
michael@0 | 161 | sprintf(key, "key%d", i); |
michael@0 | 162 | sprintf(value, "value%d", i); |
michael@0 | 163 | dict->SetKeyValue(key, value); |
michael@0 | 164 | } |
michael@0 | 165 | expectedDictionarySize = kPartitionIndex; |
michael@0 | 166 | |
michael@0 | 167 | // set a couple of the keys twice (with the same value) - should be nop |
michael@0 | 168 | dict->SetKeyValue("key2", "value2"); |
michael@0 | 169 | dict->SetKeyValue("key4", "value4"); |
michael@0 | 170 | dict->SetKeyValue("key15", "value15"); |
michael@0 | 171 | |
michael@0 | 172 | // Remove some random elements in the middle |
michael@0 | 173 | dict->RemoveKey("key7"); |
michael@0 | 174 | dict->RemoveKey("key18"); |
michael@0 | 175 | dict->RemoveKey("key23"); |
michael@0 | 176 | dict->RemoveKey("key31"); |
michael@0 | 177 | expectedDictionarySize -= 4; // we just removed four key/value pairs |
michael@0 | 178 | |
michael@0 | 179 | // Set some more key/value pairs like key59/value59, key60/value60, ... |
michael@0 | 180 | for (int i = kPartitionIndex; i < kDictionaryCapacity; ++i) { |
michael@0 | 181 | sprintf(key, "key%d", i); |
michael@0 | 182 | sprintf(value, "value%d", i); |
michael@0 | 183 | dict->SetKeyValue(key, value); |
michael@0 | 184 | } |
michael@0 | 185 | expectedDictionarySize += kDictionaryCapacity - kPartitionIndex; |
michael@0 | 186 | |
michael@0 | 187 | // Now create an iterator on the dictionary |
michael@0 | 188 | SimpleStringDictionaryIterator iter(*dict); |
michael@0 | 189 | |
michael@0 | 190 | // We then verify that it iterates through exactly the number of |
michael@0 | 191 | // key/value pairs we expect, and that they match one-for-one with what we |
michael@0 | 192 | // would expect. The ordering of the iteration does not matter... |
michael@0 | 193 | |
michael@0 | 194 | // used to keep track of number of occurrences found for key/value pairs |
michael@0 | 195 | int count[kDictionaryCapacity]; |
michael@0 | 196 | memset(count, 0, sizeof(count)); |
michael@0 | 197 | |
michael@0 | 198 | int totalCount = 0; |
michael@0 | 199 | |
michael@0 | 200 | const KeyValueEntry *entry; |
michael@0 | 201 | |
michael@0 | 202 | while ((entry = iter.Next())) { |
michael@0 | 203 | totalCount++; |
michael@0 | 204 | |
michael@0 | 205 | // Extract keyNumber from a string of the form key<keyNumber> |
michael@0 | 206 | int keyNumber; |
michael@0 | 207 | sscanf(entry->GetKey(), "key%d", &keyNumber); |
michael@0 | 208 | |
michael@0 | 209 | // Extract valueNumber from a string of the form value<valueNumber> |
michael@0 | 210 | int valueNumber; |
michael@0 | 211 | sscanf(entry->GetValue(), "value%d", &valueNumber); |
michael@0 | 212 | |
michael@0 | 213 | // The value number should equal the key number since that's how we set them |
michael@0 | 214 | STAssertTrue(keyNumber == valueNumber, nil); |
michael@0 | 215 | |
michael@0 | 216 | // Key and value numbers should be in proper range: |
michael@0 | 217 | // 0 <= keyNumber < kDictionaryCapacity |
michael@0 | 218 | bool isKeyInGoodRange = |
michael@0 | 219 | (keyNumber >= 0 && keyNumber < kDictionaryCapacity); |
michael@0 | 220 | bool isValueInGoodRange = |
michael@0 | 221 | (valueNumber >= 0 && valueNumber < kDictionaryCapacity); |
michael@0 | 222 | STAssertTrue(isKeyInGoodRange, nil); |
michael@0 | 223 | STAssertTrue(isValueInGoodRange, nil); |
michael@0 | 224 | |
michael@0 | 225 | if (isKeyInGoodRange && isValueInGoodRange) { |
michael@0 | 226 | ++count[keyNumber]; |
michael@0 | 227 | } |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | // Make sure each of the key/value pairs showed up exactly one time, except |
michael@0 | 231 | // for the ones which we removed. |
michael@0 | 232 | for (int i = 0; i < kDictionaryCapacity; ++i) { |
michael@0 | 233 | // Skip over key7, key18, key23, and key31, since we removed them |
michael@0 | 234 | if (!(i == 7 || i == 18 || i == 23 || i == 31)) { |
michael@0 | 235 | STAssertTrue(count[i] == 1, nil); |
michael@0 | 236 | } |
michael@0 | 237 | } |
michael@0 | 238 | |
michael@0 | 239 | // Make sure the number of iterations matches the expected dictionary size. |
michael@0 | 240 | STAssertTrue(totalCount == expectedDictionarySize, nil); |
michael@0 | 241 | } |
michael@0 | 242 | |
michael@0 | 243 | @end |