| OLD | NEW |
| 1 // Copyright (C) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (C) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by the GPL v2 license that can | 2 // Use of this source code is governed by the GPL v2 license that can |
| 3 // be found in the LICENSE file. | 3 // be found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Basic unittesting of dm-bht using google-gtest. | 5 // Basic unittesting of dm-bht using google-gtest. |
| 6 | 6 |
| 7 #include <base/basictypes.h> | 7 #include <base/basictypes.h> |
| 8 #include <base/logging.h> | 8 #include <base/logging.h> |
| 9 #include <base/scoped_ptr.h> | 9 #include <base/scoped_ptr.h> |
| 10 #include <gtest/gtest.h> | 10 #include <gtest/gtest.h> |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 hash_data_.reset(new u8[to_bytes(sectors_)]); | 100 hash_data_.reset(new u8[to_bytes(sectors_)]); |
| 101 } | 101 } |
| 102 dm_bht_set_write_cb(bht_.get(), MemoryBhtTest::WriteCallback); | 102 dm_bht_set_write_cb(bht_.get(), MemoryBhtTest::WriteCallback); |
| 103 dm_bht_set_read_cb(bht_.get(), MemoryBhtTest::ReadCallback); | 103 dm_bht_set_read_cb(bht_.get(), MemoryBhtTest::ReadCallback); |
| 104 } | 104 } |
| 105 void SetupBht(const unsigned int depth, | 105 void SetupBht(const unsigned int depth, |
| 106 const unsigned int total_blocks, | 106 const unsigned int total_blocks, |
| 107 const char *digest_algorithm) { | 107 const char *digest_algorithm) { |
| 108 NewBht(depth, total_blocks, digest_algorithm); | 108 NewBht(depth, total_blocks, digest_algorithm); |
| 109 | 109 |
| 110 u8 data[PAGE_SIZE]; | 110 u8 data[PAGE_SIZE] = { 0 }; |
| 111 // Store all the block hashes of blocks of 0. | |
| 112 memset(reinterpret_cast<void *>(data), 0, sizeof(data)); | |
| 113 unsigned int blocks = total_blocks; | 111 unsigned int blocks = total_blocks; |
| 114 do { | 112 do { |
| 115 EXPECT_EQ(dm_bht_store_block(bht_.get(), blocks - 1, data), 0); | 113 EXPECT_EQ(dm_bht_store_block(bht_.get(), blocks - 1, data), 0); |
| 116 } while (--blocks > 0); | 114 } while (--blocks > 0); |
| 117 | 115 |
| 118 dm_bht_set_read_cb(bht_.get(), dm_bht_zeroread_callback); | 116 dm_bht_set_read_cb(bht_.get(), dm_bht_zeroread_callback); |
| 119 EXPECT_EQ(0, dm_bht_compute(bht_.get(), NULL)); | 117 EXPECT_EQ(0, dm_bht_compute(bht_.get(), NULL)); |
| 120 EXPECT_EQ(0, dm_bht_sync(bht_.get(), reinterpret_cast<void *>(this))); | 118 EXPECT_EQ(0, dm_bht_sync(bht_.get(), reinterpret_cast<void *>(this))); |
| 121 u8 digest[1024]; | 119 u8 digest[1024]; |
| 122 dm_bht_root_hexdigest(bht_.get(), digest, sizeof(digest)); | 120 dm_bht_root_hexdigest(bht_.get(), digest, sizeof(digest)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 144 scoped_ptr<struct dm_bht> bht_; | 142 scoped_ptr<struct dm_bht> bht_; |
| 145 scoped_array<u8> hash_data_; | 143 scoped_array<u8> hash_data_; |
| 146 sector_t sectors_; | 144 sector_t sectors_; |
| 147 }; | 145 }; |
| 148 | 146 |
| 149 TEST_F(MemoryBhtTest, CreateThenVerifyOk) { | 147 TEST_F(MemoryBhtTest, CreateThenVerifyOk) { |
| 150 static const unsigned int total_blocks = 16384; | 148 static const unsigned int total_blocks = 16384; |
| 151 // Set the root hash for a 0-filled image | 149 // Set the root hash for a 0-filled image |
| 152 static const char kRootDigest[] = | 150 static const char kRootDigest[] = |
| 153 "45d65d6f9e5a962f4d80b5f1bd7a918152251c27bdad8c5f52b590c129833372"; | 151 "45d65d6f9e5a962f4d80b5f1bd7a918152251c27bdad8c5f52b590c129833372"; |
| 154 // This should match what dm_bht_store_block computed earlier. | 152 // A page of all zeros |
| 155 static const char kZeroDigest[] = | 153 static const char kZeroPage[PAGE_SIZE] = { 0 }; |
| 156 "ad7facb2586fc6e966c004d7d1d16b024f5805ff7cb47c7a85dabd8b48892ca7"; | |
| 157 u8 digest[(sizeof(kZeroDigest) - 1) >> 1]; | |
| 158 // TODO(wad) write a test for hex_to_bin and bin_to_hex | |
| 159 unsigned int digest_size = strlen(kZeroDigest) >> 1; | |
| 160 | |
| 161 dm_bht_hex_to_bin(digest, | |
| 162 reinterpret_cast<const u8 *>(kZeroDigest), | |
| 163 digest_size); | |
| 164 | 154 |
| 165 SetupBht(2, total_blocks, "sha256"); | 155 SetupBht(2, total_blocks, "sha256"); |
| 166 dm_bht_set_root_hexdigest(bht_.get(), | 156 dm_bht_set_root_hexdigest(bht_.get(), |
| 167 reinterpret_cast<const u8 *>(kRootDigest)); | 157 reinterpret_cast<const u8 *>(kRootDigest)); |
| 168 | 158 |
| 169 for (unsigned int blocks = 0; blocks < total_blocks; ++blocks) { | 159 for (unsigned int blocks = 0; blocks < total_blocks; ++blocks) { |
| 170 DLOG(INFO) << "verifying block: " << blocks; | 160 DLOG(INFO) << "verifying block: " << blocks; |
| 171 EXPECT_EQ(0, dm_bht_verify_block(bht_.get(), blocks, digest, digest_size)); | 161 EXPECT_EQ(0, dm_bht_verify_block(bht_.get(), blocks, kZeroPage)); |
| 172 } | 162 } |
| 173 | 163 |
| 174 EXPECT_EQ(0, dm_bht_destroy(bht_.get())); | 164 EXPECT_EQ(0, dm_bht_destroy(bht_.get())); |
| 175 } | 165 } |
| 176 | 166 |
| 177 TEST_F(MemoryBhtTest, CreateThenVerifyMultipleLevels) { | 167 TEST_F(MemoryBhtTest, CreateThenVerifyMultipleLevels) { |
| 178 static const unsigned int total_blocks = 16384; | 168 static const unsigned int total_blocks = 16384; |
| 179 // Set the root hash for a 0-filled image | 169 // Set the root hash for a 0-filled image |
| 180 static const char kRootDigest[] = | 170 static const char kRootDigest[] = |
| 181 "c86619624d3456f711dbb94d4ad79a4b029f6fd3b5a4a90b155c856bf5b3409b"; | 171 "c86619624d3456f711dbb94d4ad79a4b029f6fd3b5a4a90b155c856bf5b3409b"; |
| 182 // This should match what dm_bht_store_block computed earlier. | 172 // A page of all zeros |
| 183 static const char kZeroDigest[] = | 173 static const char kZeroPage[PAGE_SIZE] = { 0 }; |
| 184 "ad7facb2586fc6e966c004d7d1d16b024f5805ff7cb47c7a85dabd8b48892ca7"; | |
| 185 u8 digest[(sizeof(kZeroDigest) - 1) >> 1]; | |
| 186 // TODO(wad) write a test for hex_to_bin and bin_to_hex | |
| 187 unsigned int digest_size = strlen(kZeroDigest) >> 1; | |
| 188 | |
| 189 dm_bht_hex_to_bin(digest, | |
| 190 reinterpret_cast<const u8 *>(kZeroDigest), | |
| 191 digest_size); | |
| 192 | 174 |
| 193 SetupBht(4, total_blocks, "sha256"); | 175 SetupBht(4, total_blocks, "sha256"); |
| 194 dm_bht_set_root_hexdigest(bht_.get(), | 176 dm_bht_set_root_hexdigest(bht_.get(), |
| 195 reinterpret_cast<const u8 *>(kRootDigest)); | 177 reinterpret_cast<const u8 *>(kRootDigest)); |
| 196 | 178 |
| 197 for (unsigned int blocks = 0; blocks < total_blocks; ++blocks) { | 179 for (unsigned int blocks = 0; blocks < total_blocks; ++blocks) { |
| 198 DLOG(INFO) << "verifying block: " << blocks; | 180 DLOG(INFO) << "verifying block: " << blocks; |
| 199 EXPECT_EQ(0, dm_bht_verify_block(bht_.get(), blocks, digest, digest_size)); | 181 EXPECT_EQ(0, dm_bht_verify_block(bht_.get(), blocks, kZeroPage)); |
| 200 } | 182 } |
| 201 | 183 |
| 202 EXPECT_EQ(0, dm_bht_destroy(bht_.get())); | 184 EXPECT_EQ(0, dm_bht_destroy(bht_.get())); |
| 203 } | 185 } |
| 204 | 186 |
| 205 TEST_F(MemoryBhtTest, CreateThenVerifyOddCount) { | 187 TEST_F(MemoryBhtTest, CreateThenVerifyOddCount) { |
| 206 static const unsigned int total_blocks = 16383; | 188 static const unsigned int total_blocks = 16383; |
| 207 // Set the root hash for a 0-filled image | 189 // Set the root hash for a 0-filled image |
| 208 static const char kRootDigest[] = | 190 static const char kRootDigest[] = |
| 209 "c78d187c430465bd7831fe4908247b6ab5107e3a826d933b71e85aa9a932e03c"; | 191 "c78d187c430465bd7831fe4908247b6ab5107e3a826d933b71e85aa9a932e03c"; |
| 210 // This should match what dm_bht_store_block computed earlier. | 192 // A page of all zeros |
| 211 static const char kZeroDigest[] = | 193 static const char kZeroPage[PAGE_SIZE] = { 0 }; |
| 212 "ad7facb2586fc6e966c004d7d1d16b024f5805ff7cb47c7a85dabd8b48892ca7"; | |
| 213 u8 digest[(sizeof(kZeroDigest) - 1) >> 1]; | |
| 214 // TODO(wad) write a test for hex_to_bin and bin_to_hex | |
| 215 unsigned int digest_size = strlen(kZeroDigest) >> 1; | |
| 216 | |
| 217 dm_bht_hex_to_bin(digest, | |
| 218 reinterpret_cast<const u8 *>(kZeroDigest), | |
| 219 digest_size); | |
| 220 | 194 |
| 221 SetupBht(4, total_blocks, "sha256"); | 195 SetupBht(4, total_blocks, "sha256"); |
| 222 dm_bht_set_root_hexdigest(bht_.get(), | 196 dm_bht_set_root_hexdigest(bht_.get(), |
| 223 reinterpret_cast<const u8 *>(kRootDigest)); | 197 reinterpret_cast<const u8 *>(kRootDigest)); |
| 224 | 198 |
| 225 for (unsigned int blocks = 0; blocks < total_blocks; ++blocks) { | 199 for (unsigned int blocks = 0; blocks < total_blocks; ++blocks) { |
| 226 DLOG(INFO) << "verifying block: " << blocks; | 200 DLOG(INFO) << "verifying block: " << blocks; |
| 227 EXPECT_EQ(0, dm_bht_verify_block(bht_.get(), blocks, digest, digest_size)); | 201 EXPECT_EQ(0, dm_bht_verify_block(bht_.get(), blocks, kZeroPage)); |
| 228 } | 202 } |
| 229 | 203 |
| 230 EXPECT_EQ(0, dm_bht_destroy(bht_.get())); | 204 EXPECT_EQ(0, dm_bht_destroy(bht_.get())); |
| 231 } | 205 } |
| 232 | 206 |
| 233 TEST_F(MemoryBhtTest, CreateThenVerifyBad) { | 207 TEST_F(MemoryBhtTest, CreateThenVerifyBadHashBlock) { |
| 234 static const unsigned int total_blocks = 16384; | 208 static const unsigned int total_blocks = 16384; |
| 235 SetupBht(2, total_blocks, "sha256"); | 209 SetupBht(2, total_blocks, "sha256"); |
| 210 // A page of all zeros |
| 211 static const char kZeroPage[PAGE_SIZE] = { 0 }; |
| 236 // Set the root hash for a 0-filled image | 212 // Set the root hash for a 0-filled image |
| 237 static const char kRootDigest[] = | 213 static const char kRootDigest[] = |
| 238 "45d65d6f9e5a962f4d80b5f1bd7a918152251c27bdad8c5f52b590c129833372"; | 214 "45d65d6f9e5a962f4d80b5f1bd7a918152251c27bdad8c5f52b590c129833372"; |
| 239 dm_bht_set_root_hexdigest(bht_.get(), | 215 dm_bht_set_root_hexdigest(bht_.get(), |
| 240 reinterpret_cast<const u8 *>(kRootDigest)); | 216 reinterpret_cast<const u8 *>(kRootDigest)); |
| 241 | 217 |
| 242 // TODO(wad) add tests for partial tree validity/verification | 218 // TODO(wad) add tests for partial tree validity/verification |
| 243 | 219 |
| 244 // Corrupt one block value | 220 // Corrupt one has hblock |
| 245 static const unsigned int kBadBlock = 256; | 221 static const unsigned int kBadBlock = 256; |
| 246 u8 data[PAGE_SIZE]; | 222 u8 data[PAGE_SIZE]; |
| 247 memset(reinterpret_cast<void *>(data), 'A', sizeof(data)); | 223 memset(reinterpret_cast<void *>(data), 'A', sizeof(data)); |
| 248 EXPECT_EQ(dm_bht_store_block(bht_.get(), kBadBlock, data), 0); | 224 EXPECT_EQ(dm_bht_store_block(bht_.get(), kBadBlock, data), 0); |
| 249 | 225 |
| 250 // This should match what dm_bht_store_block computed earlier. | 226 // Attempt to verify both the bad block and all the neighbors. |
| 251 static const char kZeroDigest[] = | 227 EXPECT_LT(dm_bht_verify_block(bht_.get(), kBadBlock + 1, kZeroPage), 0); |
| 252 "ad7facb2586fc6e966c004d7d1d16b024f5805ff7cb47c7a85dabd8b48892ca7"; | |
| 253 u8 digest[(sizeof(kZeroDigest) - 1) >> 1]; | |
| 254 // TODO(wad) write a test for hex_to_bin and bin_to_hex | |
| 255 unsigned int digest_size = strlen(kZeroDigest) >> 1; | |
| 256 dm_bht_hex_to_bin(digest, | |
| 257 reinterpret_cast<const u8 *>(kZeroDigest), | |
| 258 digest_size); | |
| 259 | 228 |
| 260 // Attempt to verify both the bad block and all the neighbors. | 229 EXPECT_LT(dm_bht_verify_block(bht_.get(), kBadBlock + 2, kZeroPage), 0); |
| 261 EXPECT_LT(dm_bht_verify_block(bht_.get(), kBadBlock + 1, digest, digest_size), | 230 |
| 231 EXPECT_LT(dm_bht_verify_block(bht_.get(), kBadBlock + (bht_->node_count / 2), |
| 232 kZeroPage), |
| 262 0); | 233 0); |
| 263 | 234 |
| 264 EXPECT_LT(dm_bht_verify_block(bht_.get(), kBadBlock + 2, digest, digest_size), | 235 EXPECT_LT(dm_bht_verify_block(bht_.get(), kBadBlock, kZeroPage), 0); |
| 265 0); | |
| 266 | |
| 267 EXPECT_LT(dm_bht_verify_block(bht_.get(), kBadBlock + (bht_->node_count / 2), | |
| 268 digest, digest_size), | |
| 269 0); | |
| 270 | |
| 271 EXPECT_LT(dm_bht_verify_block(bht_.get(), kBadBlock, digest, digest_size), 0); | |
| 272 | 236 |
| 273 // Verify that the prior entry is untouched and still safe | 237 // Verify that the prior entry is untouched and still safe |
| 274 EXPECT_EQ(dm_bht_verify_block(bht_.get(), kBadBlock - 1, digest, digest_size), | 238 EXPECT_EQ(dm_bht_verify_block(bht_.get(), kBadBlock - 1, kZeroPage), 0); |
| 275 0); | |
| 276 | 239 |
| 277 // Same for the next entry | 240 // Same for the next entry |
| 278 EXPECT_EQ(dm_bht_verify_block(bht_.get(), kBadBlock + bht_->node_count, | 241 EXPECT_EQ(dm_bht_verify_block(bht_.get(), kBadBlock + bht_->node_count, |
| 279 digest, digest_size), | 242 kZeroPage), |
| 280 0); | 243 0); |
| 281 | 244 |
| 282 EXPECT_EQ(0, dm_bht_destroy(bht_.get())); | 245 EXPECT_EQ(0, dm_bht_destroy(bht_.get())); |
| 283 } | 246 } |
| 247 |
| 248 TEST_F(MemoryBhtTest, CreateThenVerifyBadDataBlock) { |
| 249 static const unsigned int total_blocks = 384; |
| 250 SetupBht(2, total_blocks, "sha256"); |
| 251 // Set the root hash for a 0-filled image |
| 252 static const char kRootDigest[] = |
| 253 "45d65d6f9e5a962f4d80b5f1bd7a918152251c27bdad8c5f52b590c129833372"; |
| 254 dm_bht_set_root_hexdigest(bht_.get(), |
| 255 reinterpret_cast<const u8 *>(kRootDigest)); |
| 256 // A corrupt page |
| 257 static const u8 kBadPage[PAGE_SIZE] = { 'A' }; |
| 258 |
| 259 EXPECT_LT(dm_bht_verify_block(bht_.get(), 0, kBadPage), 0); |
| 260 EXPECT_LT(dm_bht_verify_block(bht_.get(), 127, kBadPage), 0); |
| 261 EXPECT_LT(dm_bht_verify_block(bht_.get(), 128, kBadPage), 0); |
| 262 EXPECT_LT(dm_bht_verify_block(bht_.get(), 255, kBadPage), 0); |
| 263 EXPECT_LT(dm_bht_verify_block(bht_.get(), 256, kBadPage), 0); |
| 264 EXPECT_LT(dm_bht_verify_block(bht_.get(), 383, kBadPage), 0); |
| 265 |
| 266 EXPECT_EQ(0, dm_bht_destroy(bht_.get())); |
| 267 } |
| OLD | NEW |