pw_kvs: Restructure KVS fuzz tests
- Rename the standalone KVS fuzz test to be host fuzz test
- Split out the device-compatible fuzz test out in to its own test
- Increase max sectors for device tests to be 1024 to be compatible
with testing on the 3.5MB partition
Change-Id: I49998f3e0c6eaa1f9736fd6e5648239b07d1c362
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/41282
Reviewed-by: Armando Montanez <amontanez@google.com>
Commit-Queue: David Rogers <davidrogers@google.com>
diff --git a/pw_kvs/BUILD b/pw_kvs/BUILD
index 82c4002..3a1680b 100644
--- a/pw_kvs/BUILD
+++ b/pw_kvs/BUILD
@@ -382,8 +382,8 @@
)
pw_cc_test(
- name = "key_value_store_fuzz_test",
- srcs = ["key_value_store_fuzz_test.cc"],
+ name = "key_value_store_put_test",
+ srcs = ["key_value_store_put_test.cc"],
deps = [
":crc16",
":pw_kvs",
diff --git a/pw_kvs/BUILD.gn b/pw_kvs/BUILD.gn
index a8d84ab..e94ebaa 100644
--- a/pw_kvs/BUILD.gn
+++ b/pw_kvs/BUILD.gn
@@ -213,6 +213,19 @@
sources = [ "key_value_store_initialized_test.cc" ]
}
+pw_source_set("key_value_store_fuzz_test") {
+ deps = [
+ ":crc16",
+ ":flash_test_partition",
+ ":pw_kvs",
+ dir_pw_bytes,
+ dir_pw_checksum,
+ dir_pw_log,
+ dir_pw_unit_test,
+ ]
+ sources = [ "key_value_store_fuzz_test.cc" ]
+}
+
pw_source_set("test_key_value_store_test") {
deps = [
":pw_kvs",
@@ -248,9 +261,10 @@
":key_value_store_test",
":key_value_store_small_flash_test",
":key_value_store_64_alignment_flash_test",
+ ":key_value_store_fuzz_64_alignment_flash_test",
":key_value_store_256_alignment_flash_test",
":key_value_store_binary_format_test",
- ":key_value_store_fuzz_test",
+ ":key_value_store_put_test",
":key_value_store_map_test",
":fake_flash_test_key_value_store_test",
":sectors_test",
@@ -350,6 +364,13 @@
]
}
+pw_test("key_value_store_fuzz_64_alignment_flash_test") {
+ deps = [
+ ":fake_flash_64_aligned_partition",
+ ":key_value_store_fuzz_test",
+ ]
+}
+
pw_test("key_value_store_256_alignment_flash_test") {
deps = [
":fake_flash_256_aligned_partition",
@@ -368,14 +389,14 @@
sources = [ "key_value_store_binary_format_test.cc" ]
}
-pw_test("key_value_store_fuzz_test") {
+pw_test("key_value_store_put_test") {
deps = [
":crc16",
":fake_flash",
":pw_kvs",
":test_partition",
]
- sources = [ "key_value_store_fuzz_test.cc" ]
+ sources = [ "key_value_store_put_test.cc" ]
}
pw_test("fake_flash_test_key_value_store_test") {
diff --git a/pw_kvs/key_value_store_fuzz_test.cc b/pw_kvs/key_value_store_fuzz_test.cc
index 6a257d6..aaa7a34 100644
--- a/pw_kvs/key_value_store_fuzz_test.cc
+++ b/pw_kvs/key_value_store_fuzz_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Pigweed Authors
+// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
@@ -12,66 +12,96 @@
// License for the specific language governing permissions and limitations under
// the License.
+#include <array>
+#include <cstring>
+#include <span>
+
#include "gtest/gtest.h"
+#include "pw_checksum/crc16_ccitt.h"
#include "pw_kvs/crc16_checksum.h"
-#include "pw_kvs/fake_flash_memory.h"
-#include "pw_kvs/flash_partition_with_stats.h"
+#include "pw_kvs/flash_memory.h"
+#include "pw_kvs/flash_test_partition.h"
#include "pw_kvs/key_value_store.h"
+#include "pw_log/log.h"
+#include "pw_status/status.h"
namespace pw::kvs {
namespace {
using std::byte;
-#ifndef PW_KVS_FUZZ_ITERATIONS
-#define PW_KVS_FUZZ_ITERATIONS 2
-#endif // PW_KVS_FUZZ_ITERATIONS
-constexpr int kFuzzIterations = PW_KVS_FUZZ_ITERATIONS;
-
constexpr size_t kMaxEntries = 256;
-constexpr size_t kMaxUsableSectors = 256;
+constexpr size_t kMaxUsableSectors = 1024;
-// 4 x 4k sectors, 16 byte alignment
-FakeFlashMemoryBuffer<4 * 1024, 6> test_flash(16);
-
-FlashPartitionWithStatsBuffer<kMaxUsableSectors> test_partition(
- &test_flash, 0, test_flash.sector_count());
+constexpr std::array<const char*, 3> keys{"TestKey1", "Key2", "TestKey3"};
ChecksumCrc16 checksum;
+// For KVS magic value always use a random 32 bit integer rather than a
+// human readable 4 bytes. See pw_kvs/format.h for more information.
+constexpr EntryFormat default_format{.magic = 0x749c361e,
+ .checksum = &checksum};
+} // namespace
-class EmptyInitializedKvs : public ::testing::Test {
- protected:
- // For KVS magic value always use a random 32 bit integer rather than a
- // human readable 4 bytes. See pw_kvs/format.h for more information.
- EmptyInitializedKvs()
- : kvs_(&test_partition, {.magic = 0x873a9b50, .checksum = &checksum}) {
- test_partition.Erase(0, test_partition.sector_count());
- ASSERT_EQ(OkStatus(), kvs_.Init());
+TEST(KvsFuzz, FuzzTest) {
+ FlashPartition& test_partition = FlashTestPartition();
+ test_partition.Erase();
+
+ KeyValueStoreBuffer<kMaxEntries, kMaxUsableSectors> kvs_(&test_partition,
+ default_format);
+
+ ASSERT_EQ(OkStatus(), kvs_.Init());
+
+ if (test_partition.sector_size_bytes() < 4 * 1024 ||
+ test_partition.sector_count() < 4) {
+ PW_LOG_INFO("Sectors too small, skipping test.");
+ return; // TODO: Test could be generalized
+ }
+ const char* key1 = "Buf1";
+ const char* key2 = "Buf2";
+ const size_t kLargestBufSize = 3 * 1024;
+ static byte buf1[kLargestBufSize];
+ static byte buf2[kLargestBufSize];
+ std::memset(buf1, 1, sizeof(buf1));
+ std::memset(buf2, 2, sizeof(buf2));
+
+ // Start with things in KVS
+ ASSERT_EQ(OkStatus(), kvs_.Put(key1, buf1));
+ ASSERT_EQ(OkStatus(), kvs_.Put(key2, buf2));
+ for (size_t j = 0; j < keys.size(); j++) {
+ ASSERT_EQ(OkStatus(), kvs_.Put(keys[j], j));
}
- KeyValueStoreBuffer<kMaxEntries, kMaxUsableSectors> kvs_;
-};
+ for (size_t i = 0; i < 100; i++) {
+ // Vary two sizes
+ size_t size1 = (kLargestBufSize) / (i + 1);
+ size_t size2 = (kLargestBufSize) / (100 - i);
+ for (size_t j = 0; j < 50; j++) {
+ // Rewrite a single key many times, can fill up a sector
+ ASSERT_EQ(OkStatus(), kvs_.Put("some_data", j));
+ }
+ // Delete and re-add everything
+ ASSERT_EQ(OkStatus(), kvs_.Delete(key1));
+ ASSERT_EQ(OkStatus(), kvs_.Put(key1, std::span(buf1, size1)));
+ ASSERT_EQ(OkStatus(), kvs_.Delete(key2));
+ ASSERT_EQ(OkStatus(), kvs_.Put(key2, std::span(buf2, size2)));
+ for (size_t j = 0; j < keys.size(); j++) {
+ ASSERT_EQ(OkStatus(), kvs_.Delete(keys[j]));
+ ASSERT_EQ(OkStatus(), kvs_.Put(keys[j], j));
+ }
-TEST_F(EmptyInitializedKvs, Put_VaryingKeysAndValues) {
- char value[] =
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // 52
- "34567890123"; // 64 (with final \0);
- static_assert(sizeof(value) == 64);
-
- test_partition.ResetCounters();
-
- for (int i = 0; i < kFuzzIterations; ++i) {
- for (unsigned key_size = 1; key_size < sizeof(value); ++key_size) {
- for (unsigned value_size = 0; value_size < sizeof(value); ++value_size) {
- ASSERT_EQ(OkStatus(),
- kvs_.Put(std::string_view(value, key_size),
- std::as_bytes(std::span(value, value_size))));
- }
+ // Re-enable and verify
+ ASSERT_EQ(OkStatus(), kvs_.Init());
+ static byte buf[4 * 1024];
+ ASSERT_EQ(OkStatus(), kvs_.Get(key1, std::span(buf, size1)).status());
+ ASSERT_EQ(std::memcmp(buf, buf1, size1), 0);
+ ASSERT_EQ(OkStatus(), kvs_.Get(key2, std::span(buf, size2)).status());
+ ASSERT_EQ(std::memcmp(buf2, buf2, size2), 0);
+ for (size_t j = 0; j < keys.size(); j++) {
+ size_t ret = 1000;
+ ASSERT_EQ(OkStatus(), kvs_.Get(keys[j], &ret));
+ ASSERT_EQ(ret, j);
}
}
-
- test_partition.SaveStorageStats(kvs_, "fuzz Put_VaryingKeysAndValues");
}
-} // namespace
} // namespace pw::kvs
diff --git a/pw_kvs/key_value_store_initialized_test.cc b/pw_kvs/key_value_store_initialized_test.cc
index 9994fb6..1b1f820 100644
--- a/pw_kvs/key_value_store_initialized_test.cc
+++ b/pw_kvs/key_value_store_initialized_test.cc
@@ -36,7 +36,7 @@
using std::byte;
constexpr size_t kMaxEntries = 256;
-constexpr size_t kMaxUsableSectors = 256;
+constexpr size_t kMaxUsableSectors = 1024;
FlashPartition& test_partition = FlashTestPartition();
@@ -408,60 +408,6 @@
}
}
-TEST_F(EmptyInitializedKvs, FuzzTest) {
- if (test_partition.sector_size_bytes() < 4 * 1024 ||
- test_partition.sector_count() < 4) {
- PW_LOG_INFO("Sectors too small, skipping test.");
- return; // TODO: Test could be generalized
- }
- const char* key1 = "Buf1";
- const char* key2 = "Buf2";
- const size_t kLargestBufSize = 3 * 1024;
- static byte buf1[kLargestBufSize];
- static byte buf2[kLargestBufSize];
- std::memset(buf1, 1, sizeof(buf1));
- std::memset(buf2, 2, sizeof(buf2));
-
- // Start with things in KVS
- ASSERT_EQ(OkStatus(), kvs_.Put(key1, buf1));
- ASSERT_EQ(OkStatus(), kvs_.Put(key2, buf2));
- for (size_t j = 0; j < keys.size(); j++) {
- ASSERT_EQ(OkStatus(), kvs_.Put(keys[j], j));
- }
-
- for (size_t i = 0; i < 100; i++) {
- // Vary two sizes
- size_t size1 = (kLargestBufSize) / (i + 1);
- size_t size2 = (kLargestBufSize) / (100 - i);
- for (size_t j = 0; j < 50; j++) {
- // Rewrite a single key many times, can fill up a sector
- ASSERT_EQ(OkStatus(), kvs_.Put("some_data", j));
- }
- // Delete and re-add everything
- ASSERT_EQ(OkStatus(), kvs_.Delete(key1));
- ASSERT_EQ(OkStatus(), kvs_.Put(key1, std::span(buf1, size1)));
- ASSERT_EQ(OkStatus(), kvs_.Delete(key2));
- ASSERT_EQ(OkStatus(), kvs_.Put(key2, std::span(buf2, size2)));
- for (size_t j = 0; j < keys.size(); j++) {
- ASSERT_EQ(OkStatus(), kvs_.Delete(keys[j]));
- ASSERT_EQ(OkStatus(), kvs_.Put(keys[j], j));
- }
-
- // Re-enable and verify
- ASSERT_EQ(OkStatus(), kvs_.Init());
- static byte buf[4 * 1024];
- ASSERT_EQ(OkStatus(), kvs_.Get(key1, std::span(buf, size1)).status());
- ASSERT_EQ(std::memcmp(buf, buf1, size1), 0);
- ASSERT_EQ(OkStatus(), kvs_.Get(key2, std::span(buf, size2)).status());
- ASSERT_EQ(std::memcmp(buf2, buf2, size2), 0);
- for (size_t j = 0; j < keys.size(); j++) {
- size_t ret = 1000;
- ASSERT_EQ(OkStatus(), kvs_.Get(keys[j], &ret));
- ASSERT_EQ(ret, j);
- }
- }
-}
-
TEST_F(EmptyInitializedKvs, Basic) {
// Add some data
uint8_t value1 = 0xDA;
diff --git a/pw_kvs/key_value_store_put_test.cc b/pw_kvs/key_value_store_put_test.cc
new file mode 100644
index 0000000..5c9c97c
--- /dev/null
+++ b/pw_kvs/key_value_store_put_test.cc
@@ -0,0 +1,77 @@
+// Copyright 2020 The Pigweed Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+
+#include "gtest/gtest.h"
+#include "pw_kvs/crc16_checksum.h"
+#include "pw_kvs/fake_flash_memory.h"
+#include "pw_kvs/flash_partition_with_stats.h"
+#include "pw_kvs/key_value_store.h"
+
+namespace pw::kvs {
+namespace {
+
+using std::byte;
+
+#ifndef PW_KVS_PUT_ITERATIONS
+#define PW_KVS_PUT_ITERATIONS 2
+#endif // PW_KVS_PUT_ITERATIONS
+constexpr int kPutIterations = PW_KVS_PUT_ITERATIONS;
+
+constexpr size_t kMaxEntries = 256;
+constexpr size_t kMaxUsableSectors = 256;
+
+// 4 x 4k sectors, 16 byte alignment
+FakeFlashMemoryBuffer<4 * 1024, 6> test_flash(16);
+
+FlashPartitionWithStatsBuffer<kMaxUsableSectors> test_partition(
+ &test_flash, 0, test_flash.sector_count());
+
+ChecksumCrc16 checksum;
+
+class EmptyInitializedKvs : public ::testing::Test {
+ protected:
+ // For KVS magic value always use a random 32 bit integer rather than a
+ // human readable 4 bytes. See pw_kvs/format.h for more information.
+ EmptyInitializedKvs()
+ : kvs_(&test_partition, {.magic = 0x873a9b50, .checksum = &checksum}) {
+ test_partition.Erase(0, test_partition.sector_count());
+ ASSERT_EQ(OkStatus(), kvs_.Init());
+ }
+
+ KeyValueStoreBuffer<kMaxEntries, kMaxUsableSectors> kvs_;
+};
+
+TEST_F(EmptyInitializedKvs, Put_VaryingKeysAndValues) {
+ char value[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" // 52
+ "34567890123"; // 64 (with final \0);
+ static_assert(sizeof(value) == 64);
+
+ test_partition.ResetCounters();
+
+ for (int i = 0; i < kPutIterations; ++i) {
+ for (unsigned key_size = 1; key_size < sizeof(value); ++key_size) {
+ for (unsigned value_size = 0; value_size < sizeof(value); ++value_size) {
+ ASSERT_EQ(OkStatus(),
+ kvs_.Put(std::string_view(value, key_size),
+ std::as_bytes(std::span(value, value_size))));
+ }
+ }
+ }
+
+ test_partition.SaveStorageStats(kvs_, "Put_VaryingKeysAndValues");
+}
+
+} // namespace
+} // namespace pw::kvs