1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "oob_doubler.h"
6 
7 #include <ddktl/protocol/nand.h>
8 #include <unittest/unittest.h>
9 
10 namespace {
11 
12 constexpr uint32_t kPageSize = 100;
13 constexpr uint32_t kOobSize = 10;
14 constexpr uint32_t kBlockSize = 50;
15 constexpr size_t kOpSize = 42;
16 constexpr size_t kUnchanged = 20;
17 
18 class NandTester : public ddk::NandProtocol<NandTester> {
19   public:
NandTester()20     NandTester() : proto_({&nand_protocol_ops_, this}) {
21         info_.page_size = kPageSize;
22         info_.oob_size = kOobSize;
23         info_.pages_per_block = kBlockSize;
24         info_.num_blocks = kUnchanged;
25         info_.ecc_bits = kUnchanged;
26     }
27 
proto()28     nand_protocol_t* proto() { return &proto_; }
operation()29     nand_operation_t* operation() { return &operation_; }
30 
NandQuery(fuchsia_hardware_nand_Info * out_info,size_t * out_nand_op_size)31     void NandQuery(fuchsia_hardware_nand_Info* out_info, size_t* out_nand_op_size) {
32         *out_info = info_;
33         *out_nand_op_size = kOpSize;
34     }
35 
NandQueue(nand_operation_t * operation,nand_queue_callback callback,void * cookie)36     void NandQueue(nand_operation_t* operation, nand_queue_callback callback, void* cookie) {
37         operation_ = *operation;
38     }
39 
NandGetFactoryBadBlockList(uint32_t * out_bad_blocks_list,size_t bad_blocks_count,size_t * out_bad_blocks_actual)40     zx_status_t NandGetFactoryBadBlockList(uint32_t* out_bad_blocks_list, size_t bad_blocks_count,
41                                            size_t* out_bad_blocks_actual) {
42       return ZX_OK;
43     }
44 
45   private:
46     nand_protocol_t proto_;
47     fuchsia_hardware_nand_Info info_ = {};
48     nand_operation_t operation_ = {};
49 };
50 
TrivialLifetimeTest()51 bool TrivialLifetimeTest() {
52     BEGIN_TEST;
53     NandTester tester;
54     ftl::OobDoubler doubler(tester.proto(), false);
55     END_TEST;
56 }
57 
QueryDisabledTest()58 bool QueryDisabledTest() {
59     BEGIN_TEST;
60     NandTester tester;
61     ftl::OobDoubler doubler(tester.proto(), false);
62 
63     fuchsia_hardware_nand_Info info;
64     size_t op_size;
65     doubler.Query(&info, &op_size);
66     EXPECT_EQ(kPageSize, info.page_size);
67     EXPECT_EQ(kOobSize, info.oob_size);
68     EXPECT_EQ(kBlockSize, info.pages_per_block);
69     EXPECT_EQ(kUnchanged, info.num_blocks);
70     EXPECT_EQ(kUnchanged, info.ecc_bits);
71     EXPECT_EQ(kOpSize, op_size);
72     END_TEST;
73 }
74 
QueryEnabledTest()75 bool QueryEnabledTest() {
76     BEGIN_TEST;
77     NandTester tester;
78     ftl::OobDoubler doubler(tester.proto(), true);
79 
80     fuchsia_hardware_nand_Info info;
81     size_t op_size;
82     doubler.Query(&info, &op_size);
83     EXPECT_EQ(kPageSize * 2, info.page_size);
84     EXPECT_EQ(kOobSize * 2, info.oob_size);
85     EXPECT_EQ(kBlockSize / 2, info.pages_per_block);
86     EXPECT_EQ(kUnchanged, info.num_blocks);
87     EXPECT_EQ(kUnchanged, info.ecc_bits);
88     EXPECT_EQ(kOpSize, op_size);
89     END_TEST;
90 }
91 
QueueDisabledTest()92 bool QueueDisabledTest() {
93     BEGIN_TEST;
94     NandTester tester;
95     ftl::OobDoubler doubler(tester.proto(), false);
96 
97     nand_operation_t op = {};
98     op.command = NAND_OP_READ;
99     op.rw.length = 5;
100     op.rw.offset_nand = 6;
101     op.rw.offset_data_vmo = 7;
102     op.rw.offset_oob_vmo = 8;
103     doubler.Queue(&op, nullptr, nullptr);
104 
105     nand_operation_t* result = tester.operation();
106     EXPECT_EQ(NAND_OP_READ, result->command);
107     EXPECT_EQ(5, result->rw.length);
108     EXPECT_EQ(6, result->rw.offset_nand);
109     EXPECT_EQ(7, result->rw.offset_data_vmo);
110     EXPECT_EQ(8, result->rw.offset_oob_vmo);
111     END_TEST;
112 }
113 
QueueEnabledTest()114 bool QueueEnabledTest() {
115     BEGIN_TEST;
116     NandTester tester;
117     ftl::OobDoubler doubler(tester.proto(), true);
118 
119     nand_operation_t op = {};
120     op.command = NAND_OP_READ;
121     op.rw.length = 5;
122     op.rw.offset_nand = 6;
123     op.rw.offset_data_vmo = 7;
124     op.rw.offset_oob_vmo = 8;
125     doubler.Queue(&op, nullptr, nullptr);
126 
127     nand_operation_t* result = tester.operation();
128     EXPECT_EQ(NAND_OP_READ, result->command);
129     EXPECT_EQ(10, result->rw.length);
130     EXPECT_EQ(12, result->rw.offset_nand);
131     EXPECT_EQ(14, result->rw.offset_data_vmo);
132     EXPECT_EQ(16, result->rw.offset_oob_vmo);
133     END_TEST;
134 }
135 
136 }  // namespace
137 
138 BEGIN_TEST_CASE(OobDoublerTests)
139 RUN_TEST_SMALL(TrivialLifetimeTest)
140 RUN_TEST_SMALL(QueryDisabledTest)
141 RUN_TEST_SMALL(QueryEnabledTest)
142 RUN_TEST_SMALL(QueueDisabledTest)
143 RUN_TEST_SMALL(QueueEnabledTest)
144 END_TEST_CASE(OobDoublerTests)
145