| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <gtest/gtest.h> |
| |
| #include "ftl_private.h" |
| #include "lib/ftl/ndm-driver.h" |
| |
| namespace { |
| |
| class MockDriver final : public ftl::NdmBaseDriver { |
| public: |
| MockDriver() : NdmBaseDriver(ftl::DefaultLogger()) {} |
| ~MockDriver() final {} |
| |
| void set_incomplete(bool value) { incomplete_ = value; } |
| void set_result(int result) { result_ = result; } |
| void set_empty(bool value) { empty_ = value; } |
| |
| void GetNdmDriver(NDMDrvr* driver) { FillNdmDriver({}, true, driver); } |
| |
| // NdmDriver interface: |
| const char* Init() final { return nullptr; } |
| const char* Attach(const ftl::Volume* ftl_volume) final { return nullptr; } |
| bool Detach() final { return true; } |
| int NandRead(uint32_t start_page, uint32_t page_count, void* page_buffer, void* oob_buffer) final; |
| int NandWrite(uint32_t start_page, uint32_t page_count, const void* page_buffer, |
| const void* oob_buffer) final; |
| int NandErase(uint32_t page_num) final; |
| int IsBadBlock(uint32_t page_num) final { return ftl::kFalse; } |
| bool IsEmptyPage(uint32_t page_num, const uint8_t* data, const uint8_t* spare) final; |
| bool IncompletePageWrite(uint8_t* spare, uint8_t* data) final { return incomplete_; } |
| uint32_t PageSize() final { return 4096; } |
| uint8_t SpareSize() final { return 16; } |
| |
| private: |
| int result_ = ftl::kNdmOk; |
| bool empty_ = true; |
| bool incomplete_ = false; |
| }; |
| |
| int MockDriver::NandRead(uint32_t start_page, uint32_t page_count, void* page_buffer, |
| void* oob_buffer) { |
| return result_; |
| } |
| |
| int MockDriver::NandWrite(uint32_t start_page, uint32_t page_count, const void* page_buffer, |
| const void* oob_buffer) { |
| return result_; |
| } |
| |
| int MockDriver::NandErase(uint32_t page_num) { return result_; } |
| |
| bool MockDriver::IsEmptyPage(uint32_t page_num, const uint8_t* data, const uint8_t* spare) { |
| return empty_; |
| } |
| |
| TEST(NdmDriverTest, CheckPageEccError) { |
| MockDriver driver; |
| |
| NDMDrvr ndm; |
| driver.GetNdmDriver(&ndm); |
| ASSERT_NE(nullptr, ndm.data_and_spare_check); |
| |
| driver.set_result(ftl::kNdmUncorrectableEcc); |
| |
| int status; |
| EXPECT_EQ(ftl::kNdmOk, ndm.data_and_spare_check(0, nullptr, nullptr, &status, &driver)); |
| EXPECT_EQ(NDM_PAGE_INVALID, status); |
| } |
| |
| TEST(NdmDriverTest, CheckPageFatalError) { |
| MockDriver driver; |
| |
| NDMDrvr ndm; |
| driver.GetNdmDriver(&ndm); |
| ASSERT_NE(nullptr, ndm.data_and_spare_check); |
| |
| driver.set_result(ftl::kNdmFatalError); |
| |
| int status; |
| EXPECT_EQ(ftl::kNdmOk, ndm.data_and_spare_check(0, nullptr, nullptr, &status, &driver)); |
| EXPECT_EQ(NDM_PAGE_INVALID, status); |
| } |
| |
| TEST(NdmDriverTest, CheckPageEmpty) { |
| MockDriver driver; |
| |
| NDMDrvr ndm; |
| driver.GetNdmDriver(&ndm); |
| ASSERT_NE(nullptr, ndm.data_and_spare_check); |
| |
| int status; |
| EXPECT_EQ(ftl::kNdmOk, ndm.data_and_spare_check(0, nullptr, nullptr, &status, &driver)); |
| EXPECT_EQ(NDM_PAGE_ERASED, status); |
| } |
| |
| TEST(NdmDriverTest, CheckPageValid) { |
| MockDriver driver; |
| |
| NDMDrvr ndm; |
| driver.GetNdmDriver(&ndm); |
| ASSERT_NE(nullptr, ndm.data_and_spare_check); |
| |
| driver.set_result(ftl::kNdmUnsafeEcc); |
| driver.set_empty(false); |
| |
| int status; |
| EXPECT_EQ(ftl::kNdmOk, ndm.data_and_spare_check(0, nullptr, nullptr, &status, &driver)); |
| EXPECT_EQ(NDM_PAGE_VALID, status); |
| } |
| |
| TEST(NdmDriverTest, CheckPageValidIncompleteWrite) { |
| MockDriver driver; |
| |
| NDMDrvr ndm; |
| driver.GetNdmDriver(&ndm); |
| ASSERT_NE(nullptr, ndm.data_and_spare_check); |
| |
| driver.set_result(ftl::kNdmUnsafeEcc); |
| driver.set_incomplete(true); |
| |
| int status; |
| EXPECT_EQ(ftl::kNdmOk, ndm.data_and_spare_check(0, nullptr, nullptr, &status, &driver)); |
| EXPECT_EQ(NDM_PAGE_INVALID, status); |
| } |
| |
| } // namespace |