blob: 0721e4eca2797c8d4495b73b10b5a3cb4e01f47e [file] [log] [blame]
// Copyright 2022 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 "src/connectivity/ethernet/drivers/gvnic/bigendian.h"
#include <stdint.h>
#include <string.h>
#include <zxtest/zxtest.h>
namespace gvnic {
// "Le" tests verify that this machine is little endian, and does not use the BigEndian class.
// "Be" tests check the actual BigEndian class.
// The uint8_t is an edge case. No actual swappage occurs.
TEST(BigEndianTest, Be8) {
BigEndian<uint8_t> value;
uint8_t *bytes = reinterpret_cast<uint8_t *>(&value);
EXPECT_EQ(sizeof(BigEndian<uint8_t>), 1);
// Check that reads are (not) swapped correctly.
bytes[0] = 0x01U;
EXPECT_EQ(0x01U, value);
EXPECT_EQ(0x01U, value.GetBE());
// Check that writes are (not) swapped correctly.
value = 0xf1U;
EXPECT_EQ(0xf1U, bytes[0]);
// Check that SetBE also does nothing.
EXPECT_EQ(0xa1U, value.SetBE(0xa1U));
EXPECT_EQ(0xa1U, bytes[0]);
}
TEST(BigEndianTest, Le16) {
uint16_t value;
uint8_t i, *bytes = reinterpret_cast<uint8_t *>(&value);
// Check that reads are swapped correctly.
for (i = 0; i < sizeof(uint16_t); i++) {
bytes[i] = i + 0x01U;
}
EXPECT_EQ(0x0201U, value);
// Check that writes are swapped correctly.
value = 0xf2f1;
for (i = 0; i < sizeof(uint16_t); i++) {
EXPECT_EQ(i + 0xf1U, bytes[i]);
}
}
TEST(BigEndianTest, Be16) {
BigEndian<uint16_t> value;
uint8_t i, *bytes = reinterpret_cast<uint8_t *>(&value);
// Check that reads are swapped correctly.
for (i = 0; i < sizeof(BigEndian<uint16_t>); i++) {
bytes[i] = i + 0x01U;
}
EXPECT_EQ(0x0102U, value);
EXPECT_EQ(0x0201U, value.GetBE());
// Check that writes are swapped correctly.
value = 0xf1f2U;
for (i = 0; i < sizeof(BigEndian<uint16_t>); i++) {
EXPECT_EQ(i + 0xf1U, bytes[i]);
}
// Check that SetBE is not swapped when stored, but returns swapped.
EXPECT_EQ(value.SetBE(0xa2a1U), 0xa1a2U);
for (i = 0; i < sizeof(BigEndian<uint16_t>); i++) {
EXPECT_EQ(i + 0xa1U, bytes[i]);
}
}
TEST(BigEndianTest, Le32) {
uint32_t value;
uint8_t i, *bytes = reinterpret_cast<uint8_t *>(&value);
// Check that reads are swapped correctly.
for (i = 0; i < sizeof(uint32_t); i++) {
bytes[i] = i + 0x01U;
}
EXPECT_EQ(0x04030201U, value);
// Check that writes are swapped correctly.
value = 0xf4f3f2f1U;
for (i = 0; i < sizeof(uint32_t); i++) {
EXPECT_EQ(i + 0xf1U, bytes[i]);
}
}
TEST(BigEndianTest, Be32) {
BigEndian<uint32_t> value;
uint8_t i, *bytes = reinterpret_cast<uint8_t *>(&value);
// Check that reads are swapped correctly.
for (i = 0; i < sizeof(BigEndian<uint32_t>); i++) {
bytes[i] = i + 0x01U;
}
EXPECT_EQ(0x01020304U, value);
EXPECT_EQ(0x04030201U, value.GetBE());
// Check that writes are swapped correctly.
value = 0xf1f2f3f4U;
for (i = 0; i < sizeof(BigEndian<uint32_t>); i++) {
EXPECT_EQ(i + 0xf1U, bytes[i]);
}
// Check that SetBE is not swapped when stored, but returns swapped.
EXPECT_EQ(value.SetBE(0xa4a3a2a1U), 0xa1a2a3a4U);
for (i = 0; i < sizeof(BigEndian<uint16_t>); i++) {
EXPECT_EQ(i + 0xa1U, bytes[i]);
}
}
TEST(BigEndianTest, Le64) {
uint64_t value;
uint8_t i, *bytes = reinterpret_cast<uint8_t *>(&value);
// Check that reads are swapped correctly.
for (i = 0; i < sizeof(uint64_t); i++) {
bytes[i] = i + 0x01U;
}
EXPECT_EQ(0x0807060504030201U, value);
// Check that writes are swapped correctly.
value = 0xf8f7f6f5f4f3f2f1U;
for (i = 0; i < sizeof(uint64_t); i++) {
EXPECT_EQ(i + 0xf1U, bytes[i]);
}
}
TEST(BigEndianTest, Be64) {
BigEndian<uint64_t> value;
uint8_t i, *bytes = reinterpret_cast<uint8_t *>(&value);
// Check that reads are swapped correctly.
for (i = 0; i < sizeof(BigEndian<uint64_t>); i++) {
bytes[i] = i + 0x01U;
}
EXPECT_EQ(0x0102030405060708U, value);
EXPECT_EQ(0x0807060504030201U, value.GetBE());
// Check that writes are swapped correctly.
value = 0xf1f2f3f4f5f6f7f8U;
for (i = 0; i < sizeof(BigEndian<uint64_t>); i++) {
EXPECT_EQ(i + 0xf1U, bytes[i]);
}
// Check that SetBE is not swapped when stored, but returns swapped.
EXPECT_EQ(value.SetBE(0xa8a7a6a5a4a3a2a1U), 0xa1a2a3a4a5a6a7a8U);
for (i = 0; i < sizeof(BigEndian<uint16_t>); i++) {
EXPECT_EQ(i + 0xa1U, bytes[i]);
}
}
// The Gvnic spec breaks 64bit values into two 32bit halves, first hi then lo.
// This checks that it is equivalent to a 64bit value, which is more convenient to use.
TEST(BigEndianTest, HiLoBe32IsBe64) {
union {
struct {
BigEndian<uint32_t> hi;
BigEndian<uint32_t> lo;
} half;
BigEndian<uint64_t> value;
} hilo;
hilo.half.hi = 0xaabbccddU;
hilo.half.lo = 0x11223344U;
EXPECT_EQ(0xaabbccdd11223344U, hilo.value);
EXPECT_EQ(0x44332211ddccbbaaU, hilo.value.GetBE());
hilo.value = 0xfeedfacecafef00dU;
EXPECT_EQ(0xfeedfaceU, hilo.half.hi);
EXPECT_EQ(0xcafef00dU, hilo.half.lo);
EXPECT_EQ(0xcefaedfeU, hilo.half.hi.GetBE());
EXPECT_EQ(0x0df0fecaU, hilo.half.lo.GetBE());
hilo.value.SetBE(0x1baddeadbeefd00dU);
EXPECT_EQ(0x0dd0efbeU, hilo.half.hi);
EXPECT_EQ(0xaddead1bU, hilo.half.lo);
EXPECT_EQ(0xbeefd00dU, hilo.half.hi.GetBE());
EXPECT_EQ(0x1baddeadU, hilo.half.lo.GetBE());
}
} // namespace gvnic