summaryrefslogtreecommitdiffstats
path: root/test/oemrouter_unittest.cpp
blob: ec79316148f4f4f6d587a2b7a29779f0c33e19e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <host-ipmid/ipmid-api.h>

#include <cstring>
#include <host-ipmid/oemrouter.hpp>

#include "sample.h"

#include <gtest/gtest.h>

// Watch for correct singleton behavior.
static oem::Router* singletonUnderTest;

static ipmid_callback_t wildHandler;

static ipmi_netfn_t lastNetFunction;

// Fake ipmi_register_callback() for this test.
void ipmi_register_callback(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                            ipmi_context_t context, ipmid_callback_t cb,
                            ipmi_cmd_privilege_t priv)
{
    EXPECT_EQ(NETFUN_OEM_GROUP, netfn);
    EXPECT_EQ(IPMI_CMD_WILDCARD, cmd);
    EXPECT_EQ(reinterpret_cast<void*>(singletonUnderTest), context);
    EXPECT_EQ(PRIVILEGE_OEM, priv);
    lastNetFunction = netfn;
    wildHandler = cb;
}

namespace oem
{

namespace
{
void MakeRouter()
{
    if (!singletonUnderTest)
    {
        singletonUnderTest = mutableRouter();
    }
    ASSERT_EQ(singletonUnderTest, mutableRouter());
}

void ActivateRouter()
{
    MakeRouter();
    singletonUnderTest->activate();
    ASSERT_EQ(NETFUN_OEM_GROUP, lastNetFunction);
}

void RegisterWithRouter(Number oen, ipmi_cmd_t cmd, Handler cb)
{
    ActivateRouter();
    singletonUnderTest->registerHandler(oen, cmd, cb);
}

uint8_t msgPlain[] = {0x56, 0x34, 0x12};
uint8_t replyPlain[] = {0x56, 0x34, 0x12, 0x31, 0x41};
uint8_t msgPlus2[] = {0x67, 0x45, 0x23, 0x10, 0x20};
uint8_t msgBadOen[] = {0x57, 0x34, 0x12};

void RegisterTwoWays(ipmi_cmd_t* nextCmd)
{
    Handler f = [](ipmi_cmd_t cmd, const uint8_t* reqBuf, uint8_t* replyBuf,
                   size_t* dataLen) {
        // Check inputs
        EXPECT_EQ(0x78, cmd);
        EXPECT_EQ(0, *dataLen); // Excludes OEN

        // Generate reply.
        *dataLen = 2;
        std::memcpy(replyBuf, replyPlain + 3, *dataLen);
        return 0;
    };
    RegisterWithRouter(0x123456, 0x78, f);

    *nextCmd = IPMI_CMD_WILDCARD;
    Handler g = [nextCmd](ipmi_cmd_t cmd, const uint8_t* reqBuf,
                          uint8_t* replyBuf, size_t* dataLen) {
        // Check inputs
        EXPECT_EQ(*nextCmd, cmd);
        EXPECT_EQ(2, *dataLen); // Excludes OEN
        if (2 != *dataLen)
        {
            return 0xE0;
        }
        EXPECT_EQ(msgPlus2[3], reqBuf[0]);
        EXPECT_EQ(msgPlus2[4], reqBuf[1]);

        // Generate reply.
        *dataLen = 0;
        return 0;
    };
    RegisterWithRouter(0x234567, IPMI_CMD_WILDCARD, g);
}
} // namespace

TEST(OemRouterTest, MakeRouterProducesConsistentSingleton)
{
    MakeRouter();
}

TEST(OemRouterTest, ActivateRouterSetsLastNetToOEMGROUP)
{
    lastNetFunction = 0;
    ActivateRouter();
}

TEST(OemRouterTest, VerifiesSpecificCommandMatches)
{
    ipmi_cmd_t cmd;
    uint8_t reply[256];
    size_t dataLen;

    RegisterTwoWays(&cmd);

    dataLen = 3;
    EXPECT_EQ(0, wildHandler(NETFUN_OEM_GROUP, 0x78, msgPlain, reply, &dataLen,
                             nullptr));
    EXPECT_EQ(5, dataLen);
    EXPECT_EQ(replyPlain[0], reply[0]);
    EXPECT_EQ(replyPlain[1], reply[1]);
    EXPECT_EQ(replyPlain[2], reply[2]);
    EXPECT_EQ(replyPlain[3], reply[3]);
    EXPECT_EQ(replyPlain[4], reply[4]);
}

TEST(OemRouterTest, WildCardMatchesTwoRandomCodes)
{
    ipmi_cmd_t cmd;
    uint8_t reply[256];
    size_t dataLen;

    RegisterTwoWays(&cmd);

    // Check two random command codes.
    dataLen = 5;
    cmd = 0x89;
    EXPECT_EQ(0, wildHandler(NETFUN_OEM_GROUP, cmd, msgPlus2, reply, &dataLen,
                             nullptr));
    EXPECT_EQ(3, dataLen);

    dataLen = 5;
    cmd = 0x67;
    EXPECT_EQ(0, wildHandler(NETFUN_OEM_GROUP, cmd, msgPlus2, reply, &dataLen,
                             nullptr));
    EXPECT_EQ(3, dataLen);
}

TEST(OemRouterTest, CommandsAreRejectedIfInvalid)
{
    ipmi_cmd_t cmd;
    uint8_t reply[256];
    size_t dataLen;

    RegisterTwoWays(&cmd);

    // Message too short to include whole OEN?
    dataLen = 2;
    EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID,
              wildHandler(NETFUN_OEM_GROUP, 0x78, msgPlain, reply, &dataLen,
                          nullptr));

    // Wrong specific command?
    dataLen = 3;
    EXPECT_EQ(IPMI_CC_INVALID, wildHandler(NETFUN_OEM_GROUP, 0x89, msgPlain,
                                           reply, &dataLen, nullptr));

    // Wrong OEN?
    dataLen = 3;
    EXPECT_EQ(IPMI_CC_INVALID, wildHandler(NETFUN_OEM_GROUP, 0x78, msgBadOen,
                                           reply, &dataLen, nullptr));
}

} // namespace oem
OpenPOWER on IntegriCloud