15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2007, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Chris Demetriou
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains the unit tests for the ProfileData class.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined HAVE_STDINT_H
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h>             // to get uintptr_t
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined HAVE_INTTYPES_H
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <inttypes.h>           // another place uintptr_t might be defined
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h>
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "profiledata.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Some helpful macros for the test class
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TEST_F(cls, fn)    void cls :: fn()
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> class scoped_array {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_array(T* data) : data_(data) { }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~scoped_array() { delete[] data_; }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* get() { return data_; }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T& operator[](int i) { return data_[i]; }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* const data_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Re-runs fn until it doesn't cause EINTR.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NO_INTR(fn)   do {} while ((fn) < 0 && errno == EINTR)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Read up to "count" bytes from file descriptor "fd" into the buffer
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// starting at "buf" while handling short reads and EINTR.  On
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// success, return the number of bytes read.  Otherwise, return -1.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static ssize_t ReadPersistent(const int fd, void *buf, const size_t count) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GE(fd, 0);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *buf0 = reinterpret_cast<char *>(buf);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t num_bytes = 0;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (num_bytes < count) {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssize_t len;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NO_INTR(len = read(fd, buf0 + num_bytes, count - num_bytes));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (len < 0) {  // There was an error other than EINTR.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (len == 0) {  // Reached EOF.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_bytes += len;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(num_bytes <= count);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return num_bytes;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Thin wrapper around a file descriptor so that the file descriptor
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gets closed for sure.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FileDescriptor {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int fd_;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit FileDescriptor(int fd) : fd_(fd) {}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~FileDescriptor() {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (fd_ >= 0) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_INTR(close(fd_));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int get() { return fd_; }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// must be the same as with ProfileData::Slot.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef uintptr_t ProfileDataSlot;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Quick and dirty function to make a number into a void* for use in a
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sample.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void* V(intptr_t x) { return reinterpret_cast<void*>(x); }
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// String returned by ProfileDataChecker helper functions to indicate success.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kNoError[] = "";
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProfileDataChecker {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataChecker() {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* tmpdir = getenv("TMPDIR");
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tmpdir == NULL)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tmpdir = "/tmp";
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mkdir(tmpdir, 0755);     // if necessary
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    filename_ = string(tmpdir) + "/profiledata_unittest.tmp";
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string filename() const { return filename_; }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks the first 'num_slots' profile data slots in the file
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // against the data pointed to by 'slots'.  Returns kNoError if the
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // data matched, otherwise returns an indication of the cause of the
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // mismatch.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string Check(const ProfileDataSlot* slots, int num_slots) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CheckWithSkips(slots, num_slots, NULL, 0);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks the first 'num_slots' profile data slots in the file
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // against the data pointed to by 'slots', skipping over entries
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // described by 'skips' and 'num_skips'.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 'skips' must be a sorted list of (0-based) slot numbers to be
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // skipped, of length 'num_skips'.  Note that 'num_slots' includes
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any skipped slots, i.e., the first 'num_slots' profile data slots
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will be considered, but some may be skipped.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns kNoError if the data matched, otherwise returns an
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // indication of the cause of the mismatch.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string CheckWithSkips(const ProfileDataSlot* slots, int num_slots,
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const int* skips, int num_skips);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Validate that a profile is correctly formed.  The profile is
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // assumed to have been created by the same kind of binary (e.g.,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same slot size, same endian, etc.) as is validating the profile.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns kNoError if the profile appears valid, otherwise returns
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // an indication of the problem with the profile.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string ValidateProfile();
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string filename_;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProfileDataChecker::CheckWithSkips(const ProfileDataSlot* slots,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int num_slots, const int* skips,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int num_skips) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptor fd(open(filename_.c_str(), O_RDONLY));
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fd.get() < 0)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "file open error";
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_array<ProfileDataSlot> filedata(new ProfileDataSlot[num_slots]);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t expected_bytes = num_slots * sizeof filedata[0];
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t bytes_read = ReadPersistent(fd.get(), filedata.get(), expected_bytes);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (expected_bytes != bytes_read)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "file too small";
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < num_slots; i++) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (num_skips > 0 && *skips == i) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_skips--;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      skips++;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (slots[i] != filedata[i])
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "data mismatch";
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kNoError;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string ProfileDataChecker::ValidateProfile() {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptor fd(open(filename_.c_str(), O_RDONLY));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fd.get() < 0)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "file open error";
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat statbuf;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fstat(fd.get(), &statbuf) != 0)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "fstat error";
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (statbuf.st_size != static_cast<ssize_t>(statbuf.st_size))
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "file impossibly large";
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t filesize = statbuf.st_size;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_array<char> filedata(new char[filesize]);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ReadPersistent(fd.get(), filedata.get(), filesize) != filesize)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "read of whole file failed";
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Must have enough data for the header and the trailer.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filesize < (5 + 3) * sizeof(ProfileDataSlot))
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "not enough data in profile for header + trailer";
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check the header
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reinterpret_cast<ProfileDataSlot*>(filedata.get())[0] != 0)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "error in header: non-zero count";
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reinterpret_cast<ProfileDataSlot*>(filedata.get())[1] != 3)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "error in header: num_slots != 3";
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reinterpret_cast<ProfileDataSlot*>(filedata.get())[2] != 0)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "error in header: non-zero format version";
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Period (slot 3) can have any value.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reinterpret_cast<ProfileDataSlot*>(filedata.get())[4] != 0)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "error in header: non-zero padding value";
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t cur_offset = 5 * sizeof(ProfileDataSlot);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // While there are samples, skip them.  Each sample consists of
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // at least three slots.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool seen_trailer = false;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!seen_trailer) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur_offset > filesize - 3 * sizeof(ProfileDataSlot))
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "truncated sample header";
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileDataSlot* sample =
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<ProfileDataSlot*>(filedata.get() + cur_offset);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileDataSlot slots_this_sample = 2 + sample[1];
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssize_t size_this_sample = slots_this_sample * sizeof(ProfileDataSlot);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cur_offset > filesize - size_this_sample)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "truncated sample";
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sample[0] == 0 && sample[1] == 1 && sample[2] == 0) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      seen_trailer = true;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sample[0] < 1)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "error in sample: sample count < 1";
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sample[1] < 1)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return "error in sample: num_pcs < 1";
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 2; i < slots_this_sample; i++) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (sample[i] == 0)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return "error in sample: NULL PC";
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_offset += size_this_sample;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There must be at least one line in the (text) list of mapped objects,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and it must be terminated by a newline.  Note, the use of newline
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here and below Might not be reasonable on non-UNIX systems.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cur_offset >= filesize)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "no list of mapped objects";
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (filedata[filesize - 1] != '\n')
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "profile did not end with a complete line";
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (cur_offset < filesize) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* line_start = filedata.get() + cur_offset;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Find the end of the line, and replace it with a NUL for easier
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // scanning.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* line_end = strchr(line_start, '\n');
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *line_end = '\0';
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Advance past any leading space.  It's allowed in some lines,
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // but not in others.
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_leading_space = false;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* line_cur = line_start;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (*line_cur == ' ') {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      has_leading_space = true;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      line_cur++;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool found_match = false;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check for build lines.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!found_match) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_match = (strncmp(line_cur, "build=", 6) == 0);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Anything may follow "build=", and leading space is allowed.
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A line from ProcMapsIterator::FormatLine, of the form:
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 40000000-40015000 r-xp 00000000 03:01 12845071   /lib/ld-2.3.2.so
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Leading space is not allowed.  The filename may be omitted or
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // may consist of multiple words, so we scan only up to the
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // space before the filename.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!found_match) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int chars_scanned = -1;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sscanf(line_cur, "%*x-%*x %*c%*c%*c%*c %*x %*x:%*x %*d %n",
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             &chars_scanned);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_match = (chars_scanned > 0 && !has_leading_space);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A line from DumpAddressMap, of the form:
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // 40000000-40015000: /lib/ld-2.3.2.so
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Leading space is allowed.  The filename may be omitted or may
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // consist of multiple words, so we scan only up to the space
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // before the filename.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!found_match) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int chars_scanned = -1;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sscanf(line_cur, "%*x-%*x: %n", &chars_scanned);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_match = (chars_scanned > 0);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!found_match)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "unrecognized line in text section";
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cur_offset += (line_end - line_start) + 1;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kNoError;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProfileDataTest {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectStopped() {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(collector_.enabled());
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectRunningSamples(int samples) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileData::State state;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    collector_.GetCurrentState(&state);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(state.enabled);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(samples, state.samples_gathered);
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ExpectSameState(const ProfileData::State& before,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const ProfileData::State& after) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(before.enabled, after.enabled);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(before.samples_gathered, after.samples_gathered);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(before.start_time, after.start_time);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_STREQ(before.profile_name, after.profile_name);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData        collector_;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataChecker checker_;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The tests to run
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OpsWhenStopped();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartStopEmpty();
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartStopNoOptionsEmpty();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartWhenStarted();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartStopEmpty2();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CollectOne();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CollectTwoMatching();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CollectTwoFlush();
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartResetRestart();
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RUN(test)  do {                         \
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    printf("Running %s\n", #test);              \
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileDataTest pdt;                        \
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pdt.test();                                 \
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int RUN_ALL_TESTS() {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RUN(OpsWhenStopped);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RUN(StartStopEmpty);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RUN(StartWhenStarted);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RUN(StartStopEmpty2);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RUN(CollectOne);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RUN(CollectTwoMatching);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RUN(CollectTwoFlush);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RUN(StartResetRestart);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that various operations are safe when stopped.
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileDataTest, OpsWhenStopped) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(collector_.enabled());
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that state is disabled, all-empty/all-0
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::State state_before;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.GetCurrentState(&state_before);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(state_before.enabled);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, state_before.samples_gathered);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, state_before.start_time);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ("", state_before.profile_name);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Safe to call stop again.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Stop();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Safe to call FlushTable.
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.FlushTable();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Safe to call Add.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *trace[] = { V(100), V(101), V(102), V(103), V(104) };
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Add(arraysize(trace), trace);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::State state_after;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.GetCurrentState(&state_after);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectSameState(state_before, state_after);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start and Stop, collecting no samples.  Verify output contents.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileDataTest, StartStopEmpty) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int frequency = 1;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataSlot slots[] = {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 3, 0, 1000000 / frequency, 0,    // binary header
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 1, 0                             // binary trailer
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::Options options;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.set_frequency(frequency);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options));
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(0);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Stop();
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.ValidateProfile());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots)));
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start and Stop with no options, collecting no samples.  Verify
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// output contents.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileDataTest, StartStopNoOptionsEmpty) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're not requesting a specific period, implementation can do
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // whatever it likes.
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataSlot slots[] = {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 3, 0, 0 /* skipped */, 0,        // binary header
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 1, 0                             // binary trailer
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int slots_to_skip[] = { 3 };
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(collector_.Start(checker_.filename().c_str(),
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               ProfileData::Options()));
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(0);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Stop();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.ValidateProfile());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.CheckWithSkips(slots, arraysize(slots),
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              slots_to_skip,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              arraysize(slots_to_skip)));
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start after already started.  Should return false and not impact
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// collected data or state.
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileDataTest, StartWhenStarted) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int frequency = 1;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataSlot slots[] = {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 3, 0, 1000000 / frequency, 0,    // binary header
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 1, 0                             // binary trailer
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::Options options;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.set_frequency(frequency);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options));
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::State state_before;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.GetCurrentState(&state_before);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.set_frequency(frequency * 2);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(!collector_.Start("foobar", options));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::State state_after;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.GetCurrentState(&state_after);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectSameState(state_before, state_after);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Stop();
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.ValidateProfile());
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots)));
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Like StartStopEmpty, but uses a different file name and frequency.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileDataTest, StartStopEmpty2) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int frequency = 2;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataSlot slots[] = {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 3, 0, 1000000 / frequency, 0,    // binary header
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 1, 0                             // binary trailer
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::Options options;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.set_frequency(frequency);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options));
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(0);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Stop();
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.ValidateProfile());
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots)));
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileDataTest, CollectOne) {
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int frequency = 2;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataSlot slots[] = {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 3, 0, 1000000 / frequency, 0,    // binary header
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1, 5, 100, 101, 102, 103, 104,      // our sample
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 1, 0                             // binary trailer
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::Options options;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.set_frequency(frequency);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options));
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(0);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *trace[] = { V(100), V(101), V(102), V(103), V(104) };
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Add(arraysize(trace), trace);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(1);
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Stop();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.ValidateProfile());
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots)));
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileDataTest, CollectTwoMatching) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int frequency = 2;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataSlot slots[] = {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 3, 0, 1000000 / frequency, 0,    // binary header
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    2, 5, 100, 201, 302, 403, 504,      // our two samples
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 1, 0                             // binary trailer
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::Options options;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.set_frequency(frequency);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options));
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(0);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const void *trace[] = { V(100), V(201), V(302), V(403), V(504) };
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    collector_.Add(arraysize(trace), trace);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExpectRunningSamples(i + 1);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Stop();
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.ValidateProfile());
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots)));
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileDataTest, CollectTwoFlush) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int frequency = 2;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataSlot slots[] = {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 3, 0, 1000000 / frequency, 0,    // binary header
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1, 5, 100, 201, 302, 403, 504,      // first sample (flushed)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1, 5, 100, 201, 302, 403, 504,      // second identical sample
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 1, 0                             // binary trailer
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::Options options;
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.set_frequency(frequency);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options));
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(0);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *trace[] = { V(100), V(201), V(302), V(403), V(504) };
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Add(arraysize(trace), trace);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(1);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.FlushTable();
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Add(arraysize(trace), trace);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(2);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Stop();
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.ValidateProfile());
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots)));
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Start then reset, verify that the result is *not* a valid profile.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Then start again and make sure the result is OK.
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ProfileDataTest, StartResetRestart) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileData::Options options;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.set_frequency(1);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options));
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(0);
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Reset();
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We expect the resulting file to be empty.  This is a minimal test
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of ValidateProfile.
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(kNoError, checker_.ValidateProfile());
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat statbuf;
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, stat(checker_.filename().c_str(), &statbuf));
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, statbuf.st_size);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int frequency = 2;  // Different frequency than used above.
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileDataSlot slots[] = {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 3, 0, 1000000 / frequency, 0,    // binary header
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0, 1, 0                             // binary trailer
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.set_frequency(frequency);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(collector_.Start(checker_.filename().c_str(), options));
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectRunningSamples(0);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  collector_.Stop();
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExpectStopped();
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.ValidateProfile());
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(kNoError, checker_.Check(slots, arraysize(slots)));
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = ProfileDataTest::RUN_ALL_TESTS();
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  printf("%s\n", rc == 0 ? "PASS" : "FAIL");
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
611