#include #include #include #include using namespace mesh::powerdiag; extern void powerDiagnosticsOtherTranslationUnit(); static bool command(const char* text, char* out, uint32_t now = 0) { return handleCommand(text, out, 157, now); } int main(int argc, char** argv) { assert(argc == 2); state() = Snapshot(); const char* test = argv[1]; if (!strcmp(test, "disabled")) { assert(!enabled()); decision(mask(Reason::UsbSession), 10); sleepBegin(10); sleepEnd(20); boardVeto(Reason::Board, 20); boardError(-7, 30); const Snapshot value = snapshot(1000); assert(!value.observed && !value.current && !value.calls && !value.errors); assert(!value.board_vetoes && !value.eligible_ms && !value.union_blocked_ms); } else if (!strcmp(test, "overlap")) { setEnabled(true, 10); decision(mask(Reason::UsbSession) | mask(Reason::Bridge), 10); decision(mask(Reason::Bridge), 40); decision(mask(Reason::Bridge), 50); decision(0, 60); const Snapshot value = snapshot(80); assert(value.union_blocked_ms == 50 && value.eligible_ms == 20); assert(value.blocked_ms[(int)Reason::UsbSession] == 30); assert(value.blocked_ms[(int)Reason::Bridge] == 50); assert(value.transitions[(int)Reason::UsbSession] == 1); assert(value.transitions[(int)Reason::Bridge] == 1); assert(value.seen == (mask(Reason::UsbSession) | mask(Reason::Bridge))); assert(state().eligible_ms == 0); // Formatting/snapshot does not mutate state. assert(snapshot(80).eligible_ms == 20); } else if (!strcmp(test, "freeze")) { setEnabled(true, 0); decision(mask(Reason::UsbSession), 0); decision(mask(Reason::Calibration), 50); setEnabled(false, 100); decision(mask(Reason::Bridge), 200); const Snapshot value = snapshot(1000); assert(value.union_blocked_ms == 100 && value.eligible_ms == 0); assert(value.blocked_ms[(int)Reason::UsbSession] == 50); assert(value.blocked_ms[(int)Reason::Calibration] == 50); assert(value.current == mask(Reason::Calibration)); setEnabled(true, 1100); assert(!state().observed && !state().current && !state().seen); assert(!state().union_blocked_ms && !state().eligible_ms); } else if (!strcmp(test, "reset")) { setEnabled(true, 0); decision(mask(Reason::Serial), 1); sleepBegin(1); sleepEnd(20); reset(10); assert(enabled() && !state().observed && !state().calls && !state().seen); decision(0, 11); assert(snapshot(20).eligible_ms == 9); setEnabled(false, 20); reset(30); assert(!enabled() && !state().observed && !state().eligible_ms); } else if (!strcmp(test, "wrap")) { setEnabled(true, UINT32_MAX - 9); decision(mask(Reason::Queue), UINT32_MAX - 9); decision(0, 10); assert(state().union_blocked_ms == 20); sleepBegin(UINT32_MAX - 49); sleepEnd(50); assert(state().last_call_us == 100 && !state().short_returns); sleepBegin(50); sleepEnd(149); assert(state().short_returns == 1 && state().last_call_us == 99); assert(state().calls == 2 && state().returns == 2 && state().call_us == 199); } else if (!strcmp(test, "veto_error")) { setEnabled(true, 0); decision(0, 0); sleepBegin(1); boardVeto(Reason::BridgeCleanup, 1, 7); sleepEnd(1001); assert(state().calls == 1 && state().returns == 0 && state().board_vetoes == 1); assert(state().current == mask(Reason::BridgeCleanup) && state().detail == 7); decision(0, 2); sleepBegin(2000); boardError(-17, 3); sleepEnd(3000); assert(state().errors == 1 && state().detail == -17 && state().returns == 0); assert(state().current == mask(Reason::Board)); decision(0, 4); sleepBegin(4000); sleepEnd(4000); sleepEnd(5000); assert(state().returns == 1 && state().short_returns == 1); assert(state().call_us == 0 && state().board_vetoes == 1); decision(0, 5); sleepBegin(5000); sleepEnd(5010); boardError(-9, 6); // A reported API return is not a claim that its result was successful. assert(state().returns == 2 && state().errors == 2 && state().call_us == 10); assert(state().detail == -9 && state().current == mask(Reason::Board)); } else if (!strcmp(test, "saturation")) { setEnabled(true, 0); decision(mask(Reason::Board), 0); state().union_blocked_ms = UINT32_MAX - 5; state().blocked_ms[(int)Reason::Board] = UINT32_MAX - 5; state().transitions[(int)Reason::Board] = UINT16_MAX; decision(0, 10); decision(mask(Reason::Board), 11); assert(state().union_blocked_ms == UINT32_MAX); assert(state().blocked_ms[(int)Reason::Board] == UINT32_MAX); assert(state().transitions[(int)Reason::Board] == UINT16_MAX); state().calls = state().returns = state().short_returns = UINT32_MAX; state().call_us = UINT32_MAX - 5; sleepBegin(20); sleepEnd(30); assert(state().calls == UINT32_MAX && state().returns == UINT32_MAX); assert(state().short_returns == UINT32_MAX && state().call_us == UINT32_MAX); } else if (!strcmp(test, "commands")) { char out[157]; assert(command("set powersaving.diag on", out, 1) && enabled()); assert(strstr(out, "RAM only") && strstr(out, "unchanged")); decision(mask(Reason::Calibration), 2); assert(command("set powersaving.diag on", out, 3)); assert(state().seen == mask(Reason::Calibration)); // Repeated on is not a clear. assert(command("get powersaving.diag calibration", out, 5)); assert(strstr(out, "active=1") && strstr(out, "blocked_ms=3")); assert(command("get powersaving.diag\t calls \t", out, 5)); assert(strstr(out, "calls=0")); assert(command("set powersaving.diag off \t", out, 5) && !enabled()); assert(command("clear powersaving.diag", out, 6) && !enabled()); assert(!state().observed && !state().seen); } else if (!strcmp(test, "strict")) { char out[157] = "untouched"; assert(!command("get powersaving.diagfoo", out)); assert(!command("set powersaving.diagon", out)); assert(!command("get powersaving", out)); assert(!strcmp(out, "untouched")); for (const char* text : {"set powersaving.diag", "set powersaving.diag on junk", "set powersaving.diag 1", "clear powersaving.diag all", "get powersaving.diag 9", "get powersaving.diag 01", "get powersaving.diag 1junk", "get powersaving.diag state junk"}) { assert(command(text, out)); assert(strstr(out, "Error:")); assert(!enabled() && !state().observed && !state().calls); } } else if (!strcmp(test, "format")) { char out[157]; assert(command("get powersaving.diag", out, 100)); assert(strstr(out, "age_ms=unknown") && strstr(out, "why=unobserved")); assert(command("get powersaving.diag usb.session", out, 100)); assert(strstr(out, "age_ms=unknown")); setEnabled(true, 100); decision(mask(Reason::UsbSession), 100); assert(command("get powersaving.diag state", out, 10000)); assert(strstr(out, "age_ms=9900") && strstr(out, "why=usb.session")); assert(state().decision_at_ms == 100 && state().last_ms == 100); assert(command("get powersaving.diag time", out, 10000)); assert(strstr(out, "NOT sleep residency")); assert(command("get powersaving.diag 3", out, 10000)); assert(strstr(out, "usb.session=1/9900")); } else if (!strcmp(test, "capacity")) { setEnabled(true, 0); decision(ValidMask, 0); state().union_blocked_ms = state().eligible_ms = UINT32_MAX; state().calls = state().returns = state().short_returns = UINT32_MAX; state().board_vetoes = state().errors = UINT32_MAX; state().call_us = state().max_call_us = state().last_call_us = UINT32_MAX; state().detail = INT32_MIN; for (size_t i = 0; i < ReasonCount; ++i) { state().blocked_ms[i] = UINT32_MAX; state().transitions[i] = UINT16_MAX; } for (unsigned page = 0; page <= 8; ++page) { char large[512], bounded[157]; formatPage(page, large, sizeof(large), UINT32_MAX); formatPage(page, bounded, sizeof(bounded), UINT32_MAX); assert(strlen(large) < sizeof(bounded)); assert(!strcmp(large, bounded)); } for (size_t capacity = 1; capacity < 160; ++capacity) { char guarded[162]; memset(guarded, '!', sizeof(guarded)); assert(handleCommand("get powersaving.diag time", guarded + 1, capacity, 0)); assert(guarded[0] == '!' && guarded[capacity + 1] == '!'); assert(memchr(guarded + 1, 0, capacity)); } char untouched = '!'; assert(!handleCommand("get powersaving.diag", &untouched, 0, 0)); assert(untouched == '!'); assert(!handleCommand(nullptr, &untouched, 1, 0)); assert(!handleCommand("get powersaving.diag", nullptr, 1, 0)); } else if (!strcmp(test, "shared")) { setEnabled(true, 0); powerDiagnosticsOtherTranslationUnit(); assert(state().current == mask(Reason::UsbRecovery)); assert(state().transitions[(int)Reason::UsbRecovery] == 1); } else if (!strcmp(test, "unknown_mask")) { setEnabled(true, 0); decision(UINT32_MAX, 0); assert(state().current == ValidMask && state().seen == ValidMask); assert(mask(Reason::Count) == 0 && !strcmp(reasonName(Reason::Count), "unknown")); } else assert(false); }