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 "logical-to-physical-map.h"
6
7#include <fbl/array.h>
8#include <fbl/vector.h>
9#include <unittest/unittest.h>
10#include <zircon/types.h>
11
12namespace nand {
13
14bool CheckMultiple(LogicalToPhysicalMap ltop_map, fbl::Vector<fbl::Vector<uint32_t>> expected) {
15    BEGIN_HELPER;
16    for (uint32_t copy = 0; copy < expected.size(); copy++) {
17        EXPECT_EQ(ltop_map.LogicalBlockCount(copy), expected[copy].size());
18        uint32_t i;
19        for (i = 0; i < expected[copy].size(); i++) {
20            uint32_t physical;
21            zx_status_t status = ltop_map.GetPhysical(copy, i, &physical);
22            ASSERT_EQ(status, ZX_OK);
23            EXPECT_EQ(physical, expected[copy][i]);
24        }
25        uint32_t physical;
26        zx_status_t status = ltop_map.GetPhysical(copy, i, &physical);
27        EXPECT_EQ(status, ZX_ERR_OUT_OF_RANGE);
28    }
29    END_HELPER;
30}
31
32bool Check(LogicalToPhysicalMap ltop_map, fbl::Vector<uint32_t> expected) {
33    fbl::Vector<fbl::Vector<uint32_t>> expected_;
34    expected_.push_back(fbl::move(expected));
35    return CheckMultiple(fbl::move(ltop_map), fbl::move(expected_));
36}
37
38bool SimpleTest() {
39    BEGIN_TEST;
40    LogicalToPhysicalMap ltop_map(1, 5, fbl::Array<uint32_t>());
41    EXPECT_TRUE(Check(fbl::move(ltop_map), {0, 1, 2, 3, 4}));
42    END_TEST;
43}
44
45bool SingleBadTest() {
46    BEGIN_TEST;
47    fbl::Array<uint32_t> bad_blocks(new uint32_t[1], 1);
48    bad_blocks[0] = 2;
49    LogicalToPhysicalMap ltop_map(1, 5, fbl::move(bad_blocks));
50    EXPECT_TRUE(Check(fbl::move(ltop_map), {0, 1, 3, 4}));
51    END_TEST;
52}
53
54bool FirstBadTest() {
55    BEGIN_TEST;
56    fbl::Array<uint32_t> bad_blocks(new uint32_t[1], 1);
57    bad_blocks[0] = 0;
58    LogicalToPhysicalMap ltop_map(1, 5, fbl::move(bad_blocks));
59    EXPECT_TRUE(Check(fbl::move(ltop_map), {1, 2, 3, 4}));
60    END_TEST;
61}
62
63bool LastBadTest() {
64    BEGIN_TEST;
65    fbl::Array<uint32_t> bad_blocks(new uint32_t[1], 1);
66    bad_blocks[0] = 4;
67    LogicalToPhysicalMap ltop_map(1, 5, fbl::move(bad_blocks));
68    EXPECT_TRUE(Check(fbl::move(ltop_map), {0, 1, 2, 3}));
69    END_TEST;
70}
71
72bool MultipleBadTest() {
73    BEGIN_TEST;
74    fbl::Array<uint32_t> bad_blocks(new uint32_t[3], 3);
75    bad_blocks[0] = 0;
76    bad_blocks[1] = 2;
77    bad_blocks[2] = 4;
78    LogicalToPhysicalMap ltop_map(1, 5, fbl::move(bad_blocks));
79    EXPECT_TRUE(Check(fbl::move(ltop_map), {1, 3}));
80    END_TEST;
81}
82
83bool AllBadTest() {
84    BEGIN_TEST;
85    fbl::Array<uint32_t> bad_blocks(new uint32_t[3], 3);
86    bad_blocks[0] = 0;
87    bad_blocks[1] = 1;
88    bad_blocks[2] = 2;
89    LogicalToPhysicalMap ltop_map(1, 3, fbl::move(bad_blocks));
90
91    EXPECT_EQ(ltop_map.LogicalBlockCount(0), 0);
92    uint32_t physical;
93    zx_status_t status = ltop_map.GetPhysical(0, 0, &physical);
94    EXPECT_EQ(status, ZX_ERR_OUT_OF_RANGE);
95    END_TEST;
96}
97
98bool MultipleCopiesTest() {
99    BEGIN_TEST;
100    LogicalToPhysicalMap ltop_map(4, 8, fbl::Array<uint32_t>());
101    fbl::Vector<fbl::Vector<uint32_t>> expected;
102    expected.push_back({0, 1});
103    expected.push_back({2, 3});
104    expected.push_back({4, 5});
105    expected.push_back({6, 7});
106    EXPECT_TRUE(CheckMultiple(fbl::move(ltop_map), fbl::move(expected)));
107    END_TEST;
108}
109
110bool MultipleCopiesSomeBadTest() {
111    BEGIN_TEST;
112    fbl::Array<uint32_t> bad_blocks(new uint32_t[5], 5);
113    bad_blocks[0] = 0;
114    bad_blocks[1] = 1;
115    bad_blocks[2] = 3;
116    bad_blocks[3] = 5;
117    bad_blocks[4] = 6;
118    LogicalToPhysicalMap ltop_map(2, 8, fbl::move(bad_blocks));
119    fbl::Vector<fbl::Vector<uint32_t>> expected;
120    expected.push_back({2});
121    expected.push_back({4, 7});
122    EXPECT_TRUE(CheckMultiple(fbl::move(ltop_map), fbl::move(expected)));
123    END_TEST;
124}
125
126} // namespace nand
127
128BEGIN_TEST_CASE(LtopTests)
129RUN_TEST(nand::SimpleTest)
130RUN_TEST(nand::SingleBadTest)
131RUN_TEST(nand::FirstBadTest)
132RUN_TEST(nand::LastBadTest)
133RUN_TEST(nand::AllBadTest)
134RUN_TEST(nand::MultipleCopiesTest)
135RUN_TEST(nand::MultipleCopiesSomeBadTest)
136END_TEST_CASE(LtopTests);
137