db_encryption_test.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. #include <iostream>
  7. #include <string>
  8. #include "db/db_test_util.h"
  9. #include "port/stack_trace.h"
  10. #include "rocksdb/perf_context.h"
  11. #include "test_util/sync_point.h"
  12. namespace ROCKSDB_NAMESPACE {
  13. class DBEncryptionTest : public DBTestBase {
  14. public:
  15. DBEncryptionTest()
  16. : DBTestBase("db_encryption_test", /*env_do_fsync=*/true) {}
  17. Env* GetNonEncryptedEnv() {
  18. if (encrypted_env_ != nullptr) {
  19. return (static_cast_with_check<CompositeEnvWrapper>(encrypted_env_))
  20. ->env_target();
  21. } else {
  22. return env_;
  23. }
  24. }
  25. };
  26. TEST_F(DBEncryptionTest, CheckEncrypted) {
  27. ASSERT_OK(Put("foo567", "v1.fetdq"));
  28. ASSERT_OK(Put("bar123", "v2.dfgkjdfghsd"));
  29. Close();
  30. // Open all files and look for the values we've put in there.
  31. // They should not be found if encrypted, otherwise
  32. // they should be found.
  33. std::vector<std::string> fileNames;
  34. auto status = env_->GetChildren(dbname_, &fileNames);
  35. ASSERT_OK(status);
  36. Env* target = GetNonEncryptedEnv();
  37. int hits = 0;
  38. for (auto it = fileNames.begin(); it != fileNames.end(); ++it) {
  39. if (*it == "LOCK") {
  40. continue;
  41. }
  42. auto filePath = dbname_ + "/" + *it;
  43. std::unique_ptr<SequentialFile> seqFile;
  44. auto envOptions = EnvOptions(CurrentOptions());
  45. status = target->NewSequentialFile(filePath, &seqFile, envOptions);
  46. ASSERT_OK(status);
  47. uint64_t fileSize;
  48. status = target->GetFileSize(filePath, &fileSize);
  49. ASSERT_OK(status);
  50. std::string scratch;
  51. scratch.reserve(fileSize);
  52. Slice data;
  53. status = seqFile->Read(fileSize, &data, (char*)scratch.data());
  54. ASSERT_OK(status);
  55. if (data.ToString().find("foo567") != std::string::npos) {
  56. hits++;
  57. // std::cout << "Hit in " << filePath << "\n";
  58. }
  59. if (data.ToString().find("v1.fetdq") != std::string::npos) {
  60. hits++;
  61. // std::cout << "Hit in " << filePath << "\n";
  62. }
  63. if (data.ToString().find("bar123") != std::string::npos) {
  64. hits++;
  65. // std::cout << "Hit in " << filePath << "\n";
  66. }
  67. if (data.ToString().find("v2.dfgkjdfghsd") != std::string::npos) {
  68. hits++;
  69. // std::cout << "Hit in " << filePath << "\n";
  70. }
  71. if (data.ToString().find("dfgk") != std::string::npos) {
  72. hits++;
  73. // std::cout << "Hit in " << filePath << "\n";
  74. }
  75. }
  76. if (encrypted_env_) {
  77. ASSERT_EQ(hits, 0);
  78. } else {
  79. ASSERT_GE(hits, 4);
  80. }
  81. }
  82. TEST_F(DBEncryptionTest, ReadEmptyFile) {
  83. auto defaultEnv = GetNonEncryptedEnv();
  84. // create empty file for reading it back in later
  85. auto envOptions = EnvOptions(CurrentOptions());
  86. auto filePath = dbname_ + "/empty.empty";
  87. Status status;
  88. {
  89. std::unique_ptr<WritableFile> writableFile;
  90. status = defaultEnv->NewWritableFile(filePath, &writableFile, envOptions);
  91. ASSERT_OK(status);
  92. }
  93. std::unique_ptr<SequentialFile> seqFile;
  94. status = defaultEnv->NewSequentialFile(filePath, &seqFile, envOptions);
  95. ASSERT_OK(status);
  96. std::string scratch;
  97. Slice data;
  98. // reading back 16 bytes from the empty file shouldn't trigger an assertion.
  99. // it should just work and return an empty string
  100. status = seqFile->Read(16, &data, (char*)scratch.data());
  101. ASSERT_OK(status);
  102. ASSERT_TRUE(data.empty());
  103. }
  104. TEST_F(DBEncryptionTest, NotSupportedGetFileSize) {
  105. // Validate envrypted env does not support GetFileSize.
  106. // The goal of the test is to validate the encrypted env/fs does not support
  107. // GetFileSize API on FSRandomAccessFile interface.
  108. // This test combined with the rest of the integration tests validate that
  109. // the new API GetFileSize on FSRandomAccessFile interface is not required to
  110. // be supported for database to work properly.
  111. // The GetFileSize API is used in ReadFooterFromFile() API to get the file
  112. // size. When GetFileSize API is not supported, the ReadFooterFromFile() API
  113. // will use FileSystem GetFileSize API as fallback. Refer to the
  114. // EncryptedRandomAccessFile class definition for more details.
  115. if (!encrypted_env_) {
  116. return;
  117. }
  118. auto fs = encrypted_env_->GetFileSystem();
  119. // create empty file for reading it back in later
  120. auto filePath = dbname_ + "/empty.empty";
  121. // Create empty file
  122. CreateFile(fs.get(), filePath, "", false);
  123. // Open it for reading footer
  124. std::unique_ptr<FSRandomAccessFile> randomAccessFile;
  125. auto status = fs->NewRandomAccessFile(filePath, FileOptions(),
  126. &randomAccessFile, nullptr);
  127. ASSERT_OK(status);
  128. uint64_t fileSize;
  129. status = randomAccessFile->GetFileSize(&fileSize);
  130. ASSERT_TRUE(status.IsNotSupported());
  131. }
  132. } // namespace ROCKSDB_NAMESPACE
  133. int main(int argc, char** argv) {
  134. ROCKSDB_NAMESPACE::port::InstallStackTraceHandler();
  135. ::testing::InitGoogleTest(&argc, argv);
  136. return RUN_ALL_TESTS();
  137. }