crt: Rewrite t_intrinc with proper assertions

The previous test only exercised InterlockedIncrement and
InterlockedDecrement, used printf for output, and never returned a
failure exit code, making it useless as an automated test.

Replace it with a proper test that covers InterlockedIncrement,
InterlockedDecrement, InterlockedExchange, InterlockedExchangeAdd,
InterlockedCompareExchange, InterlockedCompareExchangePointer, and
InterlockedExchangePointer. Each function is checked for a correct
return value and correct stored value. InterlockedCompareExchange and
InterlockedCompareExchangePointer are tested with both matching and
non-matching arguments.

Signed-off-by: Jaeden Amero <jaeden@patater.com>
Signed-off-by: LIU Hao <lh_mouse@126.com>
diff --git a/mingw-w64-crt/testcases/t_intrinc.c b/mingw-w64-crt/testcases/t_intrinc.c
index 000a77e..8eb5a25 100644
--- a/mingw-w64-crt/testcases/t_intrinc.c
+++ b/mingw-w64-crt/testcases/t_intrinc.c
@@ -1,13 +1,68 @@
 #include <windows.h>
 #include <stdio.h>
 
-int main() {
-    LONG poop = 0;
-    for (int i = 0; i < 5; ++i) {
-        printf("[%02I32d]\n", InterlockedIncrement(&poop));
-    }
-    for (int j = 0; j < 5; ++j) {
-        printf("[%02I32d]\n", InterlockedDecrement(&poop));
-    }
-}
+#define TEST(cond, msg, ...) do { \
+  if (!(cond)) { \
+    fprintf(stderr, "%s:%d: " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__); \
+    return 1; \
+  } \
+} while (0)
 
+int main()
+{
+  LONG val;
+  void *ptr;
+  void *old;
+
+  /* InterlockedIncrement */
+  val = 0;
+  TEST(InterlockedIncrement(&val) == 1, "InterlockedIncrement: expected return 1, got %ld", val);
+  TEST(val == 1, "InterlockedIncrement: expected val 1, got %ld", val);
+  TEST(InterlockedIncrement(&val) == 2, "InterlockedIncrement: expected return 2, got %ld", val);
+
+  /* InterlockedDecrement */
+  val = 2;
+  TEST(InterlockedDecrement(&val) == 1, "InterlockedDecrement: expected return 1, got %ld", val);
+  TEST(val == 1, "InterlockedDecrement: expected val 1, got %ld", val);
+  TEST(InterlockedDecrement(&val) == 0, "InterlockedDecrement: expected return 0, got %ld", val);
+
+  /* InterlockedExchange */
+  val = 10;
+  TEST(InterlockedExchange(&val, 20) == 10, "InterlockedExchange: expected old 10");
+  TEST(val == 20, "InterlockedExchange: expected val 20, got %ld", val);
+
+  /* InterlockedExchangeAdd */
+  val = 100;
+  TEST(InterlockedExchangeAdd(&val, 50) == 100, "InterlockedExchangeAdd: expected old 100");
+  TEST(val == 150, "InterlockedExchangeAdd: expected val 150, got %ld", val);
+
+  /* InterlockedCompareExchange - matching comparand */
+  val = 42;
+  TEST(InterlockedCompareExchange(&val, 99, 42) == 42, "InterlockedCompareExchange: expected old 42");
+  TEST(val == 99, "InterlockedCompareExchange: expected val 99, got %ld", val);
+
+  /* InterlockedCompareExchange - non-matching comparand */
+  val = 99;
+  TEST(InterlockedCompareExchange(&val, 0, 50) == 99, "InterlockedCompareExchange: expected old 99");
+  TEST(val == 99, "InterlockedCompareExchange: expected val 99 (unchanged), got %ld", val);
+
+  /* InterlockedCompareExchangePointer - matching comparand */
+  ptr = (void *)1;
+  old = InterlockedCompareExchangePointer(&ptr, (void *)2, (void *)1);
+  TEST(old == (void *)1, "InterlockedCompareExchangePointer: expected old 1");
+  TEST(ptr == (void *)2, "InterlockedCompareExchangePointer: expected new 2");
+
+  /* InterlockedCompareExchangePointer - non-matching comparand */
+  ptr = (void *)5;
+  old = InterlockedCompareExchangePointer(&ptr, (void *)9, (void *)3);
+  TEST(old == (void *)5, "InterlockedCompareExchangePointer: expected old 5");
+  TEST(ptr == (void *)5, "InterlockedCompareExchangePointer: expected unchanged 5");
+
+  /* InterlockedExchangePointer */
+  ptr = (void *)10;
+  old = InterlockedExchangePointer(&ptr, (void *)20);
+  TEST(old == (void *)10, "InterlockedExchangePointer: expected old 10");
+  TEST(ptr == (void *)20, "InterlockedExchangePointer: expected new 20");
+
+  return 0;
+}