333 lines
9.1 KiB
C++
333 lines
9.1 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
/*
|
|
UnitTest for M5Utility
|
|
*/
|
|
#include <gtest/gtest.h>
|
|
#include <M5Utility.hpp>
|
|
#include <random>
|
|
#include <chrono>
|
|
#include <thread>
|
|
|
|
using namespace m5::utility::log;
|
|
|
|
namespace {
|
|
using pf_t = std::pair<const char* /* full path */, const char* /* filename */>;
|
|
|
|
pf_t table[] = {
|
|
{"", ""}, {nullptr, ""},
|
|
{"aaa", "aaa"}, {"ソソソソ", "ソソソソ"},
|
|
{"a/b.c", "b.c"}, {"c:/aaa/bbb/ccc/ddd.eee", "ddd.eee"},
|
|
};
|
|
|
|
} // namespace
|
|
|
|
TEST(Utility, pathToFilename)
|
|
{
|
|
{
|
|
constexpr auto fn0 = pathToFilename("");
|
|
EXPECT_STREQ(fn0, "");
|
|
constexpr auto fn1 = pathToFilename("ABC");
|
|
EXPECT_STREQ(fn1, "ABC");
|
|
constexpr auto fn2 = pathToFilename("a:/bb/ccc/dddd/eee.f");
|
|
EXPECT_STREQ(fn2, "eee.f");
|
|
}
|
|
|
|
for (auto&& e : table) {
|
|
EXPECT_STREQ(pathToFilename(e.first), e.second) << e.first;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
TEST(Utility, log) {
|
|
M5_LIB_LOGE("Error");
|
|
M5_LIB_LOGW("Warn");
|
|
M5_LIB_LOGI("Info");
|
|
M5_LIB_LOGD("Debug");
|
|
M5_LIB_LOGV("Verbose");
|
|
|
|
constexpr uint8_t test[] = {
|
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23,
|
|
0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67,
|
|
0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB,
|
|
0xCD, 0xEF, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
|
|
};
|
|
M5_DUMPE(test + 0, sizeof(test) - 0);
|
|
M5_DUMPE(test + 1, sizeof(test) - 1);
|
|
M5_DUMPE(test + 7, sizeof(test) - 07;
|
|
M5_DUMPE(test + 11, sizeof(test) - 11);
|
|
M5_DUMPE(test + 19, sizeof(test) - 19);
|
|
}
|
|
#endif
|
|
|
|
namespace {
|
|
auto rng = std::default_random_engine{};
|
|
}
|
|
|
|
TEST(Utility, BitSegment)
|
|
{
|
|
// static_assert
|
|
#if 0
|
|
{
|
|
m5::utility::BitSegment<11, int8_t> compile_error1; // 11 > 8
|
|
m5::utility::BitSegment<0, int8_t> copile_error2; // 0
|
|
}
|
|
#endif
|
|
|
|
// Constructor/Assignemt
|
|
{
|
|
using bs_t = m5::utility::BitSegment<6, uint8_t>;
|
|
bs_t v0{0x84}; // base_type constructor
|
|
bs_t v1 = v0; // same type constructor
|
|
|
|
EXPECT_EQ(v0.raw(), 0x84);
|
|
EXPECT_EQ(v0.upper(), v1.upper());
|
|
EXPECT_EQ(v0.lower(), v1.lower());
|
|
EXPECT_EQ(v0.raw(), v1.raw());
|
|
|
|
bs_t v2, v3;
|
|
EXPECT_EQ(v2.raw(), 0);
|
|
EXPECT_EQ(v2.raw(), v3.raw());
|
|
|
|
v2 = -1; // base_type assignment
|
|
EXPECT_NE(v2.raw(), v3.raw());
|
|
|
|
v3 = v2; // same type assignment
|
|
EXPECT_EQ(v2.raw(), v3.raw());
|
|
|
|
bs_t v4 = 0xC0; // base_type constructor
|
|
EXPECT_EQ(v4.raw(), 0xC0);
|
|
}
|
|
|
|
// Getter/Setter using signed
|
|
{
|
|
using bs1_t = m5::utility::BitSegment<12, int16_t>;
|
|
|
|
auto t = std::is_same<int16_t, bs1_t::base_type>::value;
|
|
EXPECT_TRUE(t);
|
|
t = std::is_same<uint16_t, bs1_t::unsigned_type>::value;
|
|
EXPECT_TRUE(t);
|
|
|
|
EXPECT_TRUE(bs1_t::SIGNED);
|
|
EXPECT_EQ(+bs1_t::UPPER_BITS, 3);
|
|
EXPECT_EQ(+bs1_t::LOWER_BITS, 12);
|
|
EXPECT_EQ(+bs1_t::UPPER_SHIFT, 12);
|
|
EXPECT_EQ(+bs1_t::UPPER_MASK, 0x07);
|
|
EXPECT_EQ(+bs1_t::LOWER_MASK, 0xFFF);
|
|
|
|
bs1_t value0;
|
|
EXPECT_EQ(value0.upper(), 0U);
|
|
EXPECT_EQ(value0.lower(), 0U);
|
|
EXPECT_EQ(value0.raw(), 0);
|
|
|
|
value0.lower(123);
|
|
EXPECT_EQ(value0.upper(), 0U);
|
|
EXPECT_EQ(value0.lower(), 123U);
|
|
EXPECT_EQ(value0.raw(), 123);
|
|
|
|
value0.lower(0x7FFF);
|
|
EXPECT_EQ(value0.upper(), 0U);
|
|
EXPECT_EQ(value0.lower(), 0x0FFFU);
|
|
EXPECT_EQ(value0.raw(), 0x0FFF);
|
|
|
|
value0.upper(5);
|
|
EXPECT_EQ(value0.upper(), 5U);
|
|
EXPECT_EQ(value0.lower(), 0xFFFU);
|
|
EXPECT_EQ(value0.raw(), 0x5FFF);
|
|
|
|
value0.upper(0xFF);
|
|
EXPECT_EQ(value0.upper(), 0x0007U);
|
|
EXPECT_EQ(value0.lower(), 0x0FFFU);
|
|
EXPECT_EQ(value0.raw(), 0x7FFF);
|
|
|
|
value0.raw(-1);
|
|
EXPECT_EQ(value0.upper(), 0x0007U);
|
|
EXPECT_EQ(value0.lower(), 0x0FFFU);
|
|
EXPECT_EQ(value0.raw(), -1);
|
|
|
|
// Keep signed bit
|
|
value0.lower(234);
|
|
EXPECT_EQ(value0.upper(), 0x0007U);
|
|
EXPECT_EQ(value0.lower(), 234U);
|
|
EXPECT_EQ(value0.raw(), -3862); // 0xF0EA
|
|
}
|
|
|
|
// Getter/Setter using unsigned
|
|
{
|
|
using bs2_t = m5::utility::BitSegment<12, const uint32_t&>;
|
|
auto t = std::is_same<uint32_t, bs2_t::base_type>::value;
|
|
EXPECT_TRUE(t);
|
|
t = std::is_same<uint32_t, bs2_t::unsigned_type>::value;
|
|
EXPECT_TRUE(t);
|
|
|
|
EXPECT_FALSE(bs2_t::SIGNED);
|
|
EXPECT_EQ(+bs2_t::UPPER_BITS, 20U);
|
|
EXPECT_EQ(+bs2_t::LOWER_BITS, 12U);
|
|
EXPECT_EQ(+bs2_t::UPPER_SHIFT, 12U);
|
|
EXPECT_EQ(+bs2_t::UPPER_MASK, 0xFFFFFU);
|
|
EXPECT_EQ(+bs2_t::LOWER_MASK, 0xFFFU);
|
|
|
|
bs2_t value0;
|
|
EXPECT_EQ(value0.upper(), 0U);
|
|
EXPECT_EQ(value0.lower(), 0U);
|
|
EXPECT_EQ(value0.raw(), 0U);
|
|
|
|
value0.lower(123);
|
|
EXPECT_EQ(value0.upper(), 0U);
|
|
EXPECT_EQ(value0.lower(), 123U);
|
|
EXPECT_EQ(value0.raw(), 123U);
|
|
|
|
value0.lower(0x00003FFF);
|
|
EXPECT_EQ(value0.upper(), 0U);
|
|
EXPECT_EQ(value0.lower(), 0x00000FFFU);
|
|
EXPECT_EQ(value0.raw(), 0x00000FFFU);
|
|
|
|
value0.upper(5);
|
|
EXPECT_EQ(value0.upper(), 5U);
|
|
EXPECT_EQ(value0.lower(), 0x00000FFFU);
|
|
EXPECT_EQ(value0.raw(), 0x00005FFFU);
|
|
|
|
value0.upper(0x84218421);
|
|
EXPECT_EQ(value0.upper(), 0x00018421U);
|
|
EXPECT_EQ(value0.lower(), 0x00000FFFU);
|
|
EXPECT_EQ(value0.raw(), 0x18421FFFU);
|
|
|
|
value0.raw(-1);
|
|
EXPECT_EQ(value0.upper(), 0x000FFFFFU);
|
|
EXPECT_EQ(value0.lower(), 0x00000FFFU);
|
|
EXPECT_EQ(value0.raw(), 0xFFFFFFFFU);
|
|
|
|
// Not include signed bit
|
|
value0.lower(234);
|
|
EXPECT_EQ(value0.upper(), 0x000FFFFFU);
|
|
EXPECT_EQ(value0.lower(), 234U);
|
|
EXPECT_EQ(value0.raw(), 4294963434U); // 0xFFFFF0EA
|
|
}
|
|
|
|
// Compare
|
|
{
|
|
using bs_t = m5::utility::BitSegment<14, int64_t>;
|
|
|
|
bs_t v0, v1;
|
|
EXPECT_TRUE(v0 == v1);
|
|
EXPECT_FALSE(v0 != v1);
|
|
EXPECT_FALSE(v0 < v1);
|
|
EXPECT_FALSE(v0 > v1);
|
|
EXPECT_TRUE(v0 <= v1);
|
|
EXPECT_TRUE(v0 >= v1);
|
|
|
|
EXPECT_TRUE(v0 == 0);
|
|
EXPECT_FALSE(v0 != 0);
|
|
EXPECT_FALSE(v0 < 0);
|
|
EXPECT_FALSE(v0 > 0);
|
|
EXPECT_TRUE(v0 <= 0);
|
|
EXPECT_TRUE(v0 >= 0);
|
|
|
|
EXPECT_TRUE(0 == v0);
|
|
EXPECT_FALSE(0 != v0);
|
|
EXPECT_FALSE(0 < v0);
|
|
EXPECT_FALSE(0 > v0);
|
|
EXPECT_TRUE(0 <= v0);
|
|
|
|
v1.lower(123);
|
|
EXPECT_FALSE(v0 == v1);
|
|
EXPECT_TRUE(v0 != v1);
|
|
EXPECT_TRUE(v0 < v1);
|
|
EXPECT_FALSE(v0 > v1);
|
|
EXPECT_TRUE(v0 <= v1);
|
|
EXPECT_FALSE(v0 >= v1);
|
|
|
|
v0.lower(987);
|
|
EXPECT_FALSE(v0 == v1);
|
|
EXPECT_TRUE(v0 != v1);
|
|
EXPECT_FALSE(v0 < v1);
|
|
EXPECT_TRUE(v0 > v1);
|
|
EXPECT_FALSE(v0 <= v1);
|
|
EXPECT_TRUE(v0 >= v1);
|
|
|
|
v0 = v1;
|
|
v1.upper(654321);
|
|
EXPECT_FALSE(v0 == v1);
|
|
EXPECT_TRUE(v0 != v1);
|
|
EXPECT_TRUE(v0 < v1);
|
|
EXPECT_FALSE(v0 > v1);
|
|
EXPECT_TRUE(v0 <= v1);
|
|
EXPECT_FALSE(v0 >= v1);
|
|
|
|
v0.upper(99999999);
|
|
EXPECT_FALSE(v0 == v1);
|
|
EXPECT_TRUE(v0 != v1);
|
|
EXPECT_FALSE(v0 < v1);
|
|
EXPECT_TRUE(v0 > v1);
|
|
EXPECT_FALSE(v0 <= v1);
|
|
EXPECT_TRUE(v0 >= v1);
|
|
|
|
v0 = v1 = 0;
|
|
|
|
v0 = -123;
|
|
v1 = -12;
|
|
EXPECT_FALSE(v0 == v1);
|
|
EXPECT_TRUE(v0 != v1);
|
|
EXPECT_TRUE(v0 < v1);
|
|
EXPECT_FALSE(v0 > v1);
|
|
EXPECT_TRUE(v0 <= v1);
|
|
EXPECT_FALSE(v0 >= v1);
|
|
|
|
v1 = -876543;
|
|
EXPECT_FALSE(v0 == v1);
|
|
EXPECT_TRUE(v0 != v1);
|
|
EXPECT_FALSE(v0 < v1);
|
|
EXPECT_TRUE(v0 > v1);
|
|
EXPECT_FALSE(v0 <= v1);
|
|
EXPECT_TRUE(v0 >= v1);
|
|
}
|
|
}
|
|
|
|
namespace {
|
|
using clock = std::chrono::high_resolution_clock;
|
|
}
|
|
|
|
TEST(Utility, comatibility)
|
|
{
|
|
// millis
|
|
{
|
|
auto ms = m5::utility::millis();
|
|
auto ams = clock::now() + std::chrono::milliseconds(1);
|
|
std::this_thread::sleep_until(ams);
|
|
EXPECT_GT(m5::utility::millis(), ms);
|
|
}
|
|
// micros
|
|
{
|
|
auto us = m5::utility::micros();
|
|
auto aus = clock::now() + std::chrono::microseconds(1);
|
|
std::this_thread::sleep_until(aus);
|
|
EXPECT_GT(m5::utility::micros(), us);
|
|
}
|
|
|
|
// delay
|
|
{
|
|
constexpr unsigned long wait{20};
|
|
auto start = clock::now();
|
|
m5::utility::delay(wait);
|
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(clock::now() - start).count();
|
|
auto elapsed2 = std::chrono::duration_cast<std::chrono::microseconds>(clock::now() - start).count();
|
|
// printf("-----> %lld %lld\n", elapsed, elapsed2);
|
|
#if defined(ARDUINO)
|
|
EXPECT_GE(elapsed,
|
|
wait - 1); // Arduino delay may return before the specified time.
|
|
#else
|
|
EXPECT_GE(elapsed, wait);
|
|
#endif
|
|
}
|
|
|
|
// delayMicroseconds
|
|
{
|
|
auto start = clock::now();
|
|
m5::utility::delayMicroseconds(1);
|
|
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(clock::now() - start).count();
|
|
EXPECT_GE(elapsed, 1);
|
|
}
|
|
}
|