blob: 58e893d4df1ecdc4754702bdb5d31b470257474d [file] [log] [blame]
// Copyright 2007 Google Inc. All Rights Reserved.
// Author: Raksit Ashok
//
// Unit test for the GetStackFrames function in stacktrace.cc.
#include <stdio.h>
#include "glog/logging.h"
#include "base/commandlineflags.h"
#include "stacktrace.h"
#include "config.h"
#include "utilities.h"
using std::min;
using namespace GOOGLE_NAMESPACE;
#ifdef HAVE_STACKTRACE
// Obtain a backtrace of the stack frame sizes, verify that they look sane.
//-----------------------------------------------------------------------//
int CheckFrameSizesLeaf(int32* i); // 8KB frame size.
int CheckFrameSizes2(int32* i); // 4KB
int CheckFrameSizes1(int32* i); // 2KB
int CheckFrameSizes(int32* i); // 1KB
//-----------------------------------------------------------------------//
// The expected frame-sizes in the backtrace.
const int BACKTRACE_STEPS = 4;
int expected_frame_sizes[BACKTRACE_STEPS] = {
1 << 13,
1 << 12,
1 << 11,
1 << 10,
};
//-----------------------------------------------------------------------//
void CheckFrameSizeIsOk(int actual_frame_size, int ref_frame_size) {
// Assume upto 512 bytes of miscellaneous stuff in CheckFrameSizes* frames.
const int misc_frame_size = 512;
CHECK_GE(actual_frame_size, ref_frame_size);
CHECK_LE(actual_frame_size, ref_frame_size + misc_frame_size);
}
//-----------------------------------------------------------------------//
int ATTRIBUTE_NOINLINE CheckFrameSizesLeaf(int32 *i) {
const int DEPTH = 10;
void* pcs[DEPTH];
int frame_sizes[DEPTH];
int size;
int32 j[2048]; // 8KB.
for (int k = 0; k < 2048; k++) j[k] = k + i[k % 1024];
for (int depth = 0; depth < DEPTH; depth++) {
size = GetStackFrames(pcs, frame_sizes, depth, 0);
printf("--- GetStackFrames(..., %d, 0) = %d\n", depth, size);
CHECK_LE(size, depth);
CHECK_GE(size, min(depth, BACKTRACE_STEPS));
for (int k = 0; k < size; k++) {
if (k < BACKTRACE_STEPS)
// GetStackFrames doesn't work correctly if we are using glibc's backtrace.
#ifndef HAVE_EXECINFO_H
CheckFrameSizeIsOk(frame_sizes[k], expected_frame_sizes[k]);
#endif
printf("frame_sizes[%d] = %d\n", k, frame_sizes[k]);
}
}
int sum = 0;
for (int k = 0; k < 2048; k++) sum += j[k];
return sum;
}
//-----------------------------------------------------------------------//
/* Dummy functions to make the frame-size backtrace more interesting. */
int ATTRIBUTE_NOINLINE CheckFrameSizes2(int32* i) {
int32 j[1024]; // 4KB.
for (int k = 0; k < 1024; k++) j[k] = k + i[k % 512];
return CheckFrameSizesLeaf(j) + j[512];
}
int ATTRIBUTE_NOINLINE CheckFrameSizes1(int32* i) {
int32 j[512]; // 2KB.
for (int k = 0; k < 512; k++) j[k] = k + i[k % 256];
return CheckFrameSizes2(j) + j[256];
}
int ATTRIBUTE_NOINLINE CheckFrameSizes(int32* i) {
int32 j[256]; // 1KB.
for (int k = 0; k < 256; k++) j[k] = k + i[k];
return CheckFrameSizes1(j) + j[128];
}
//-----------------------------------------------------------------------//
int main(int argc, char ** argv) {
FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]);
int32 i[256]; // 1KB.
for (int j = 0; j < 256; j++) i[j] = j;
int ret = CheckFrameSizes(i);
printf("CheckFrameSizes returned: %d\n", ret);
printf("PASS\n");
return 0;
}
#else
int main() {
printf("PASS (no stacktrace support)\n");
return 0;
}
#endif // HAVE_STACKTRACE