| 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; | 
| +} | 
|  |