19768d126762064fb35c6fd19e41ef9b988c3c329dgrogan@chromium.org// Copyright (c) 2013 The LevelDB Authors. All rights reserved.
29768d126762064fb35c6fd19e41ef9b988c3c329dgrogan@chromium.org// Use of this source code is governed by a BSD-style license that can be
39768d126762064fb35c6fd19e41ef9b988c3c329dgrogan@chromium.org// found in the LICENSE file. See the AUTHORS file for names of contributors.
49768d126762064fb35c6fd19e41ef9b988c3c329dgrogan@chromium.org
511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org// Test for issue 178: a manual compaction causes deleted data to reappear.
611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org#include <iostream>
711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org#include <sstream>
811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org#include <cstdlib>
911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
1011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org#include "leveldb/db.h"
1111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org#include "leveldb/write_batch.h"
1211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org#include "util/testharness.h"
1311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
1411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.orgnamespace {
1511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
1611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.orgconst int kNumKeys = 1100000;
1711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
1811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.orgstd::string Key1(int i) {
1911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  char buf[100];
2011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  snprintf(buf, sizeof(buf), "my_key_%d", i);
2111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  return buf;
2211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org}
2311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
2411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.orgstd::string Key2(int i) {
2511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  return Key1(i) + "_xxx";
2611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org}
2711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
2811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.orgclass Issue178 { };
2911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
3011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.orgTEST(Issue178, Test) {
3111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // Get rid of any state from an old run.
3211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  std::string dbpath = leveldb::test::TmpDir() + "/leveldb_cbug_test";
3311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  DestroyDB(dbpath, leveldb::Options());
3411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
3511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // Open database.  Disable compression since it affects the creation
3611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // of layers and the code below is trying to test against a very
3711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // specific scenario.
3811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  leveldb::DB* db;
3911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  leveldb::Options db_options;
4011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  db_options.create_if_missing = true;
4111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  db_options.compression = leveldb::kNoCompression;
4211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  ASSERT_OK(leveldb::DB::Open(db_options, dbpath, &db));
4311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
4411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // create first key range
4511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  leveldb::WriteBatch batch;
4611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  for (size_t i = 0; i < kNumKeys; i++) {
4711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org    batch.Put(Key1(i), "value for range 1 key");
4811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  }
4911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
5011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
5111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // create second key range
5211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  batch.Clear();
5311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  for (size_t i = 0; i < kNumKeys; i++) {
5411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org    batch.Put(Key2(i), "value for range 2 key");
5511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  }
5611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
5711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
5811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // delete second key range
5911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  batch.Clear();
6011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  for (size_t i = 0; i < kNumKeys; i++) {
6111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org    batch.Delete(Key2(i));
6211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  }
6311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
6411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
6511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // compact database
6611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  std::string start_key = Key1(0);
6711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  std::string end_key = Key1(kNumKeys - 1);
6811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  leveldb::Slice least(start_key.data(), start_key.size());
6911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  leveldb::Slice greatest(end_key.data(), end_key.size());
7011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
7111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // commenting out the line below causes the example to work correctly
7211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  db->CompactRange(&least, &greatest);
7311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
7411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // count the keys
7511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions());
7611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  size_t num_keys = 0;
7711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
7811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org    num_keys++;
7911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  }
8011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  delete iter;
8111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  ASSERT_EQ(kNumKeys, num_keys) << "Bad number of keys";
8211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
8311042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  // close database
8411042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  delete db;
8511042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  DestroyDB(dbpath, leveldb::Options());
8611042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org}
8711042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
8811042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org}  // anonymous namespace
8911042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org
9011042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.orgint main(int argc, char** argv) {
9111042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org  return leveldb::test::RunAllTests();
9211042098fe3e5a16ad70c388bb5914a907ae3faedgrogan@chromium.org}
93