mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-09-26 18:47:56 +00:00
feat(display): add R8 portrait observer layouts
This commit is contained in:
@@ -30,6 +30,7 @@ does not reflect the GoogleTest count — run the built binary directly
|
||||
| `test_mqtt_topic_router` | `src/helpers/MQTTTopicRouter.h` | complete preset/custom topic-routing contract; MeshRank all types except raw; required identifiers; invalid inputs/slots; exact buffer boundaries |
|
||||
| `test_mqtt_connection_policy` | `src/helpers/MQTTConnectionPolicy.h` | reconnect guard/backoff/stagger and breaker transitions; stable reset; JWT lifetime/renewal policy; exact timing boundaries and 32-bit `millis()` rollover; WiFi current-outage start sticky across STA reconnect attempts |
|
||||
| `test_alert_fault_policy` | `src/helpers/AlertFaultPolicy.h` | WiFi/MQTT fault edge detector; `OutageSnapshot` (down / started_ms / initiating reason) fed to tick and `formatWifiAlert`; reason-8 reconnects change neither duration nor initiating reason; flap between status polls; down at `millis()==0`; packed 64-bit cross-task word; rate-limit floor and first-fire; 5 s poll cadence and `millis()` rollover |
|
||||
| `test_display_viewport` | `src/helpers/ui/DisplayViewport.h`, `src/helpers/ui/DisplayFrameSignature.h` | logical-to-physical portrait mapping; fractional span coverage; fitted-width conversion; preferred/fallback text scaling; stable visible-frame change detection |
|
||||
| `test_mqtt_packet_queue_policy` | `src/helpers/MQTTPacketQueuePolicy.h` | queue-full eviction; stale-disconnect flush; adaptive drain limits; bounded QoS0 retries; exact timing boundaries and 32-bit `millis()` rollover |
|
||||
| `test_mqtt_packet_filter` | `src/helpers/MQTTPacketFilter.h` | per-slot 0-15 allowlist parsing/formatting, numeric and named spellings; exact bounds; membership; candidate/eligible split and retry-completion policy; pre-queue union gate; default-mask detection |
|
||||
| `test_mqtt_runtime_buffer_lifecycle` | `src/helpers/MQTTRuntimeBufferLifecycle.h` | idempotent allocation/release; partial-allocation degradation; retry of only missing buffers |
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "helpers/ui/DisplayFrameSignature.h"
|
||||
#include "helpers/ui/DisplayViewport.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace {
|
||||
|
||||
const DisplayViewport::Geometry kPortrait{ 128, 64, 240, 320 };
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(DisplayViewport, MapsLogicalBoundsToPortraitPanel) {
|
||||
EXPECT_EQ(0, kPortrait.mapX(0));
|
||||
EXPECT_EQ(240, kPortrait.mapX(128));
|
||||
EXPECT_EQ(0, kPortrait.mapY(0));
|
||||
EXPECT_EQ(320, kPortrait.mapY(64));
|
||||
}
|
||||
|
||||
TEST(DisplayViewport, MapsObserverRowsAcrossPortraitHeight) {
|
||||
EXPECT_EQ(0, kPortrait.mapY(0));
|
||||
EXPECT_EQ(70, kPortrait.mapY(14));
|
||||
EXPECT_EQ(100, kPortrait.mapY(20));
|
||||
EXPECT_EQ(120, kPortrait.mapY(24));
|
||||
EXPECT_EQ(150, kPortrait.mapY(30));
|
||||
EXPECT_EQ(200, kPortrait.mapY(40));
|
||||
EXPECT_EQ(240, kPortrait.mapY(48));
|
||||
EXPECT_EQ(250, kPortrait.mapY(50));
|
||||
}
|
||||
|
||||
TEST(DisplayViewport, FractionalHorizontalSpansHaveNoGapsOrOverlaps) {
|
||||
int16_t previous_end = 0;
|
||||
int total_width = 0;
|
||||
|
||||
for (int x = 0; x < 128; ++x) {
|
||||
int16_t start = kPortrait.mapX(x);
|
||||
int16_t end = kPortrait.mapX(x + 1);
|
||||
EXPECT_EQ(previous_end, start);
|
||||
EXPECT_TRUE(end - start == 1 || end - start == 2);
|
||||
total_width += end - start;
|
||||
previous_end = end;
|
||||
}
|
||||
|
||||
EXPECT_EQ(240, previous_end);
|
||||
EXPECT_EQ(240, total_width);
|
||||
}
|
||||
|
||||
TEST(DisplayViewport, ConvertsFittedPhysicalWidthBackToLogicalWidth) {
|
||||
EXPECT_EQ(0, kPortrait.logicalWidthForPhysical(0));
|
||||
EXPECT_EQ(64, kPortrait.logicalWidthForPhysical(120));
|
||||
EXPECT_EQ(122, kPortrait.logicalWidthForPhysical(228));
|
||||
EXPECT_EQ(128, kPortrait.logicalWidthForPhysical(240));
|
||||
}
|
||||
|
||||
TEST(DisplayViewport, SelectsPreferredTextScaleOnlyWhenItFits) {
|
||||
EXPECT_EQ(2, DisplayViewport::selectTextScale(114, 2, 1, 240));
|
||||
EXPECT_EQ(1, DisplayViewport::selectTextScale(150, 2, 1, 240));
|
||||
EXPECT_EQ(1, DisplayViewport::selectTextScale(192, 2, 1, 229));
|
||||
EXPECT_EQ(1, DisplayViewport::selectTextScale(300, 2, 1, 240));
|
||||
}
|
||||
|
||||
TEST(DisplayFrameSignature, ChangesWithVisibleContent) {
|
||||
uint32_t initial = DisplayFrameSignature::INITIAL;
|
||||
uint32_t home = DisplayFrameSignature::append(initial, "home");
|
||||
|
||||
EXPECT_EQ(home, DisplayFrameSignature::append(initial, "home"));
|
||||
EXPECT_NE(home, DisplayFrameSignature::append(initial, "setup"));
|
||||
EXPECT_NE(DisplayFrameSignature::append(home, "10.0.0.1"), DisplayFrameSignature::append(home, "10.0.0.2"));
|
||||
}
|
||||
|
||||
TEST(DisplayFrameSignature, KeepsAdjacentFieldsDistinct) {
|
||||
uint32_t first = DisplayFrameSignature::append(DisplayFrameSignature::INITIAL, "ab");
|
||||
first = DisplayFrameSignature::append(first, "c");
|
||||
|
||||
uint32_t second = DisplayFrameSignature::append(DisplayFrameSignature::INITIAL, "a");
|
||||
second = DisplayFrameSignature::append(second, "bc");
|
||||
|
||||
EXPECT_NE(first, second);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
Reference in New Issue
Block a user