blob: 92a8b932fbb45cb9efea322a0432a4252ee95b5b [file] [edit]
// Host unit test for __prof_rocm::growArray, the dynamic-array helper shared by
// the ROCm device-profile drains (InstrProfilingPlatformROCm.cpp and
// InstrProfilingPlatformROCmHSA.cpp). It is pure host logic with no GPU, HIP, or
// HSA dependency, so -- unlike the device drain tests under GPU/ and AMDGPU/,
// which require a real AMD GPU -- it runs anywhere the profile runtime is
// tested, including upstream CI on machines without a GPU.
//
// RUN: %clangxx %s -o %t
// RUN: %run %t | FileCheck %s
#include "../../lib/profile/InstrProfilingPlatformROCmInternal.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
using __prof_rocm::growArray;
static int Failures = 0;
#define EXPECT(Cond) \
do { \
if (!(Cond)) { \
fprintf(stderr, "FAIL: %s:%d: %s\n", __FILE__, __LINE__, #Cond); \
++Failures; \
} \
} while (0)
static int allZero(const int *P, int Begin, int End) {
for (int I = Begin; I < End; ++I)
if (P[I] != 0)
return 0;
return 1;
}
int main() {
// 1. Allocating from empty uses InitCap and zero-initializes every slot.
{
int *A = nullptr;
int Cap = 0;
EXPECT(growArray((void **)&A, &Cap, /*MinCount=*/1, /*InitCap=*/4,
sizeof(int)) == 0);
EXPECT(A != nullptr);
EXPECT(Cap == 4);
EXPECT(allZero(A, 0, Cap));
free(A);
}
// 2. Doubling continues until the capacity covers MinCount (4 -> 8 -> 16).
{
int *A = nullptr;
int Cap = 0;
EXPECT(growArray((void **)&A, &Cap, /*MinCount=*/10, /*InitCap=*/4,
sizeof(int)) == 0);
EXPECT(Cap == 16);
EXPECT(allZero(A, 0, Cap));
free(A);
}
// 3. When the capacity already suffices the array is left untouched.
{
int *A = (int *)malloc(8 * sizeof(int));
for (int I = 0; I < 8; ++I)
A[I] = I + 1;
int *Before = A;
int Cap = 8;
EXPECT(growArray((void **)&A, &Cap, /*MinCount=*/8, /*InitCap=*/4,
sizeof(int)) == 0);
EXPECT(A == Before);
EXPECT(Cap == 8);
EXPECT(A[0] == 1 && A[7] == 8);
free(A);
}
// 4. Growth preserves existing elements and zero-fills the new tail, with
// doubling resuming from the current capacity rather than InitCap.
{
int *A = (int *)malloc(4 * sizeof(int));
for (int I = 0; I < 4; ++I)
A[I] = 100 + I;
int Cap = 4;
EXPECT(growArray((void **)&A, &Cap, /*MinCount=*/5, /*InitCap=*/4,
sizeof(int)) == 0);
EXPECT(Cap == 8);
EXPECT(A[0] == 100 && A[1] == 101 && A[2] == 102 && A[3] == 103);
EXPECT(allZero(A, 4, Cap));
free(A);
}
// 5. ElemSize byte math is honored for wider element types.
{
struct Pair {
uint64_t A, B;
};
Pair *P = nullptr;
int Cap = 0;
EXPECT(growArray((void **)&P, &Cap, /*MinCount=*/3, /*InitCap=*/2,
sizeof(Pair)) == 0);
EXPECT(Cap == 4);
int Zeroed = 1;
for (int I = 0; I < Cap; ++I)
if (P[I].A != 0 || P[I].B != 0)
Zeroed = 0;
EXPECT(Zeroed);
free(P);
}
if (Failures == 0)
printf("PASS\n");
else
printf("%d FAILURE(S)\n", Failures);
return Failures != 0;
}
// CHECK: PASS