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