| Index: tools/cygprofile/cygprofile_android_unittest.cc
|
| diff --git a/tools/cygprofile/cygprofile_android_unittest.cc b/tools/cygprofile/cygprofile_android_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..085b1060289a5fc78470ebe6d36dfc4108f6ef07
|
| --- /dev/null
|
| +++ b/tools/cygprofile/cygprofile_android_unittest.cc
|
| @@ -0,0 +1,155 @@
|
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +// Test is intended to be executed on an Android device. The device should
|
| +// have an sd card, and should have a /sdcard/profile directory already created
|
| +// before running the test, because the test will dump the log file into that
|
| +// directory. The test will enable order profiling, call some functions and
|
| +// then disable profiling. The test will then check that the calls were
|
| +// properly logged in the log file. Since the first entry of a function is
|
| +// logged, the profiling should log the following:
|
| +// 00008000-00023000 r-xp 00000000 b3:02 12322 /data/local/tmp/cygprofile_test
|
| +// secs msecs pid:threadid func
|
| +// START
|
| +// 1315416566 712405 1818:1074467944 function2_addr
|
| +// 1315416566 712457 1818:1074467944 function1_addr
|
| +// 1315416566 712483 1818:1074467944 function3_addr
|
| +// END
|
| +// This is medium-sized unittest because it will first write the log file
|
| +// during profiling and then reads the file to make sure it contains the correct
|
| +// output. The test passes on normal exit (i.e. a 0 return value from main).
|
| +
|
| +#include <stdio.h>
|
| +#include <stdint.h>
|
| +#include <string.h>
|
| +
|
| +#include "./cygprofile_android.h"
|
| +
|
| +// Used to mod (i.e. %) seconds with to truncate the length. It seems
|
| +// reasonable to expect logged calls to be at most 999 seconds apart.
|
| +const int kTruncateSecs = 1000;
|
| +
|
| +int function1(void) {
|
| + return 0;
|
| +}
|
| +
|
| +int function2(void) {
|
| + return function1 () + 1;
|
| +}
|
| +
|
| +int function3(void) {
|
| + return function2 () + 1;
|
| +}
|
| +
|
| +int check_logfile(void) {
|
| + // Check results to see if test passed.
|
| + FILE* fp;
|
| + char line[256];
|
| + int linenum = 0;
|
| + char* str;
|
| + char* res;
|
| + unsigned long seconds, mtime, tid;
|
| + unsigned long lastsecs, lastmtime, lasttid;
|
| + int pid, addr, lastpid;
|
| +
|
| + // The test is to be run on an Android device with a sd card. Before running
|
| + // the test there should be a /sdcard/profile directory created on the device.
|
| + if ((fp=fopen("/sdcard/profile/logfile.out", "r")) == NULL) {
|
| + printf("FAIL: could not open log file: Does directory /sdcard/profile exist?\n");
|
| + return -1;
|
| + }
|
| +
|
| + // Expect exactly 7 lines in log file
|
| + for (linenum = 0; linenum < 7; linenum++) {
|
| + if (fgets(line, sizeof(line), fp) == NULL) {
|
| + printf("FAIL: log file does not contain correct number of lines\n");
|
| + return -1;
|
| + }
|
| +
|
| + // Make sure line 2 is START, last line is END, and the correct calls
|
| + // are profiled on lines 3, 4 and 5.
|
| + switch (linenum) {
|
| + case 2:
|
| + str = strtok_r(line, " \n", &res);
|
| + if (strcmp("START", str) != 0) {
|
| + printf("FAIL: START not found where expected\n");
|
| + return -1;
|
| + }
|
| + break;
|
| + case 3:
|
| + sscanf(line, "%ld %ld\t%d:%ld\t%x\n", &lastsecs, &lastmtime, &lastpid,
|
| + &lasttid, &addr);
|
| + lastsecs = lastsecs % kTruncateSecs;
|
| + if (reinterpret_cast<void*>(addr) != &function2) {
|
| + // Test failed
|
| + printf("FAIL: function2 call not found where expected\n");
|
| + printf(" line = %s, function2 = %p\n", line, &function2);
|
| + return -1;
|
| + }
|
| + // fprintf (stdout, "addr: %x, %p equal=%d\n", addr, &function2, ;
|
| + break;
|
| + case 4:
|
| + sscanf(line, "%ld %ld\t%d:%ld\t%x\n", &seconds, &mtime, &pid, &tid,
|
| + &addr);
|
| + seconds = seconds % kTruncateSecs;
|
| + if (reinterpret_cast<void*>(addr) != &function1 || pid != lastpid ||
|
| + tid != lasttid ||
|
| + ((seconds * 1000000) + mtime) < ((lastsecs * 100000) + lastmtime)) {
|
| + // Test failed
|
| + // printf("addr = %p, function1 = %p, pid = %d, lastpid = %d\n",
|
| + // reinterpret_cast<void*>(addr), &function1, pid, lastpid);
|
| + // printf("seconds = %ld, mtime = %ld, lastsecs = %ld, lastmtime = %d\n",
|
| + // seconds, mtime, lastsecs, lastmtime);
|
| + // printf("condition4: %ld < %ld\n",
|
| + // ((seconds * 1000000) + mtime), ((lastsecs * 100000) + lastmtime));
|
| + printf("FAIL: function1 call not found where expected\n");
|
| + return -1;
|
| + }
|
| + lastsecs = seconds;
|
| + lastmtime = mtime;
|
| + lastpid = pid;
|
| + lasttid = tid;
|
| + break;
|
| + case 5:
|
| + sscanf(line, "%ld %ld\t%d:%ld\t%x\n", &seconds, &mtime, &pid, &tid,
|
| + &addr);
|
| + if (reinterpret_cast<void*>(addr) != &function3 || pid != lastpid ||
|
| + tid != lasttid ||
|
| + ((seconds * 1000000) + mtime) < ((lastsecs * 100000) + lastmtime)) {
|
| + // Test failed
|
| + printf("FAIL: function3 call not found where expected\n");
|
| + return -1;
|
| + }
|
| + break;
|
| + case 6:
|
| + str = strtok_r(line, " \n", &res);
|
| + // sscanf(line, "%s%*s", str);
|
| + if (strcmp("END", str) != 0) {
|
| + printf("FAIL: END not found where expected\n");
|
| + return -1;
|
| + }
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +int main(void) {
|
| + int result, passed;
|
| + cygprofile::cygprofile_start("/sdcard/profile/logfile.out");
|
| + function2();
|
| + result = function3();
|
| + cygprofile::cygprofile_end();
|
| +
|
| + function2();
|
| + passed = check_logfile();
|
| + if (passed < 0)
|
| + printf("test failed.\n");
|
| + else
|
| + printf("test passed.\n");
|
| + return passed;
|
| +}
|
|
|