test: strengthen tests for schedTest
This commit is contained in:
1 parent
86ef404a1f
commit
0d5554866e
1 file changed
+159
+159
@@ -1411,3 +1411,162 @@ KTEST(threadSetPriorityChangesWeightOfALiveThread)
|
||||
uint32 id = threadCreate("priorityChange", noopThreadEntry);
|
||||
KT_NE(t, id, threadInvalidId);
|
||||
|
||||
KT_TRUE(t, threadSetPriority(id, 4096));
|
||||
KT_EQU(t, threadPriority(id), 4096u);
|
||||
|
||||
KT_TRUE(t, threadDiscard(id));
|
||||
}
|
||||
|
||||
KTEST(threadSetPriorityRejectsDeadOrUnusedTarget)
|
||||
{
|
||||
uint32 id = threadCreate("prioritySetOnDead", noopThreadEntry);
|
||||
KT_NE(t, id, threadInvalidId);
|
||||
|
||||
KT_TRUE(t, threadKill(id));
|
||||
KT_FALSE(t, threadSetPriority(id, 4096));
|
||||
|
||||
KT_TRUE(t, threadReap(id));
|
||||
KT_FALSE(t, threadSetPriority(id, 4096));
|
||||
}
|
||||
|
||||
KTEST(threadKillGroupKillsEveryLiveMemberAndLeavesOtherGroupsAlone)
|
||||
{
|
||||
uint32 a = threadCreate("groupKillA", noopThreadEntry);
|
||||
uint32 b = threadCreate("groupKillB", noopThreadEntry);
|
||||
uint32 outsider = threadCreate("groupKillOutsider", noopThreadEntry);
|
||||
KT_NE(t, a, threadInvalidId);
|
||||
KT_NE(t, b, threadInvalidId);
|
||||
KT_NE(t, outsider, threadInvalidId);
|
||||
|
||||
uint32 pgid = threadAt(a)->pgid;
|
||||
KT_TRUE(t, threadSetPgid(b, pgid));
|
||||
KT_NE(t, threadAt(outsider)->pgid, pgid);
|
||||
|
||||
KT_TRUE(t, threadKillGroup(pgid));
|
||||
KT_EQ(t, threadAt(a)->state, threadDead);
|
||||
KT_EQ(t, threadAt(b)->state, threadDead);
|
||||
/* A completely different group must be untouched -- the exact scoping
|
||||
property keyboard.c's real Ctrl-C/Ctrl-Z depends on (user/pgroupfg.c/
|
||||
user/pgroupbg.c is the live ring-3 proof for sigRaiseGroup's own
|
||||
version of this same scoping, signal.c). */
|
||||
KT_EQ(t, threadAt(outsider)->state, threadRunnable);
|
||||
|
||||
KT_TRUE(t, threadReap(a));
|
||||
KT_TRUE(t, threadReap(b));
|
||||
KT_TRUE(t, threadDiscard(outsider));
|
||||
}
|
||||
|
||||
KTEST(threadKillGroupReturnsFalseWhenNoLiveThreadHasThatPgid)
|
||||
{
|
||||
/* No thread created anywhere in this whole KTEST run ever uses this
|
||||
exact value as its pgid -- ids never reach anywhere near it (see
|
||||
threadCapacity/maxThreads), so it can never collide with a real
|
||||
group by coincidence. */
|
||||
KT_FALSE(t, threadKillGroup(0xBEEF0000u));
|
||||
}
|
||||
|
||||
KTEST(threadKillGroupSkipsAlreadyDeadMembersButStillReportsTheGroupAsFound)
|
||||
{
|
||||
uint32 a = threadCreate("groupKillDeadA", noopThreadEntry);
|
||||
uint32 b = threadCreate("groupKillDeadB", noopThreadEntry);
|
||||
KT_NE(t, a, threadInvalidId);
|
||||
KT_NE(t, b, threadInvalidId);
|
||||
|
||||
uint32 pgid = threadAt(a)->pgid;
|
||||
KT_TRUE(t, threadSetPgid(b, pgid));
|
||||
|
||||
/* b is killed FIRST, independently -- threadKillGroup must still find
|
||||
and kill a (already-Dead members are simply skipped, exactly like
|
||||
sigRaiseGroup below skips them via sigRaiseInfo's own Dead/Unused
|
||||
guard), and must still report true since a real target existed. */
|
||||
KT_TRUE(t, threadKill(b));
|
||||
KT_TRUE(t, threadKillGroup(pgid));
|
||||
KT_EQ(t, threadAt(a)->state, threadDead);
|
||||
|
||||
KT_TRUE(t, threadReap(a));
|
||||
KT_TRUE(t, threadReap(b));
|
||||
}
|
||||
|
||||
/* currentThreadGetEnv/currentThreadSetEnv (sched.h's new Thread.env) always
|
||||
act on whoever is "current" -- at KTEST time that is the idle thread
|
||||
(id 0, same "always-present current thread" reasoning this file's own
|
||||
header comment already gives for schedBlockCurrent above), so every test
|
||||
below resets threadAt(0)->envCount to 0 first: idle's own table is pure
|
||||
scratch space for these tests (initialEnv gives every REAL boot-time
|
||||
spawn an empty table regardless of whatever idle's own happens to hold,
|
||||
see initialEnv's own "currentIndex == 0" branch, sched.c), but leaving
|
||||
it dirty between tests would let an earlier test's entries leak into a
|
||||
later one's count/index assumptions. */
|
||||
KTEST(currentThreadSetEnvThenGetEnvRoundTrips)
|
||||
{
|
||||
threadAt(0)->envCount = 0;
|
||||
|
||||
KT_TRUE(t, currentThreadSetEnv("FOO", "bar"));
|
||||
KT_STREQ(t, currentThreadGetEnv("FOO"), "bar");
|
||||
KT_NULL(t, currentThreadGetEnv("MISSING"));
|
||||
}
|
||||
|
||||
KTEST(currentThreadSetEnvOverwritesExistingNameInPlace)
|
||||
{
|
||||
threadAt(0)->envCount = 0;
|
||||
|
||||
KT_TRUE(t, currentThreadSetEnv("FOO", "bar"));
|
||||
KT_TRUE(t, currentThreadSetEnv("FOO", "baz"));
|
||||
KT_STREQ(t, currentThreadGetEnv("FOO"), "baz");
|
||||
/* An overwrite must never consume a second slot. */
|
||||
KT_EQ(t, currentThreadEnvCount(), 1);
|
||||
}
|
||||
|
||||
KTEST(currentThreadSetEnvRejectsEntryTooLongForStorage)
|
||||
{
|
||||
threadAt(0)->envCount = 0;
|
||||
|
||||
/* envEntryMax (sched.h) bounds "NAME=VALUE\0" together -- a value long
|
||||
enough to blow that budget must be rejected outright, leaving no
|
||||
partially-written entry behind. */
|
||||
char hugeValue[envEntryMax];
|
||||
for (int i = 0; i < envEntryMax - 1; i++)
|
||||
hugeValue[i] = 'x';
|
||||
hugeValue[envEntryMax - 1] = 0;
|
||||
|
||||
KT_FALSE(t, currentThreadSetEnv("FOO", hugeValue));
|
||||
KT_NULL(t, currentThreadGetEnv("FOO"));
|
||||
KT_EQ(t, currentThreadEnvCount(), 0);
|
||||
}
|
||||
|
||||
KTEST(currentThreadSetEnvRejectsNewNameOnceTableIsFull)
|
||||
{
|
||||
threadAt(0)->envCount = 0;
|
||||
|
||||
char name[8];
|
||||
for (int i = 0; i < envMaxVars; i++) {
|
||||
snprintf(name, sizeof(name), "V%d", i);
|
||||
KT_TRUE(t, currentThreadSetEnv(name, "x"));
|
||||
}
|
||||
KT_EQ(t, currentThreadEnvCount(), envMaxVars);
|
||||
|
||||
KT_FALSE(t, currentThreadSetEnv("ONE_TOO_MANY", "x"));
|
||||
KT_EQ(t, currentThreadEnvCount(), envMaxVars);
|
||||
|
||||
/* Overwriting an EXISTING name must still work even while the table is
|
||||
completely full -- it takes the already-occupied slot, never a new
|
||||
one. */
|
||||
KT_TRUE(t, currentThreadSetEnv("V0", "changed"));
|
||||
KT_STREQ(t, currentThreadGetEnv("V0"), "changed");
|
||||
KT_EQ(t, currentThreadEnvCount(), envMaxVars);
|
||||
|
||||
threadAt(0)->envCount = 0;
|
||||
}
|
||||
|
||||
KTEST(currentThreadEnvEntryExposesRawStorageForListing)
|
||||
{
|
||||
threadAt(0)->envCount = 0;
|
||||
|
||||
KT_TRUE(t, currentThreadSetEnv("A", "1"));
|
||||
KT_TRUE(t, currentThreadSetEnv("B", "2"));
|
||||
KT_EQ(t, currentThreadEnvCount(), 2);
|
||||
KT_STREQ(t, currentThreadEnvEntry(0), "A=1");
|
||||
KT_STREQ(t, currentThreadEnvEntry(1), "B=2");
|
||||
KT_NULL(t, currentThreadEnvEntry(2));
|
||||
KT_NULL(t, currentThreadEnvEntry(-1));
|
||||
|
||||
Reference in new issue
Block a user