text: /*
   * Copyright (C) 2009 The Android Open Source Project
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *  * Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *  * Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
   * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   */
  
  
  #ifndef SYSTEM_EXTRAS_TESTS_SDCARD_TESTCASE_H_
  #define SYSTEM_EXTRAS_TESTS_SDCARD_TESTCASE_H_
  
  #include <stdlib.h>
  #include "stopwatch.h"
  #include "sysutil.h"
  
  namespace android_test {
  
  // Class to group test parameters and implementation.
  // Takes care of forking child processes and wait for them.
  
  class TestCase {
    public:
      enum Type {UNKNOWN_TEST, WRITE, READ, OPEN_CREATE, READ_WRITE};
      enum Pipe {READ_FROM_CHILD = 0, WRITE_TO_PARENT, READ_FROM_PARENT, WRITE_TO_CHILD};
      enum Sync {NO_SYNC, FSYNC, SYNC};
  
      // Reads takes less time than writes. This is a basic
      // approximation of how much longer the read tasks must run to
      // terminate roughly at the same time as the write tasks.
      const static int kReadWriteFactor = 5;
  
      TestCase(const char *appName);
  
      ~TestCase();
  
      size_t iter() const { return mIter; }
      void setIter(size_t iter);
  
      size_t nproc() const { return mNproc; }
      void setNproc(size_t val) { mNproc = val; }
  
      size_t dataSize() const { return mDataSize; }
      void setDataSize(size_t val) { mDataSize = val; }
  
      size_t chunkSize() const { return mChunkSize; }
      void setChunkSize(size_t val) { mChunkSize = val; }
  
      bool newFairSleepers() const { return mNewFairSleepers; }
      void setNewFairSleepers(bool val) {
          mNewFairSleepers = val;
          android::setNewFairSleepers(val);
      }
  
      bool normalizedSleepers() const { return mNormalizedSleepers; }
      void setNormalizedSleepers(bool val) {
          mNormalizedSleepers = val;
          android::setNormalizedSleepers(val);
      }
  
      Sync sync() const { return mSync; }
      void setSync(Sync s);
      const char *syncAsStr() const;
  
      bool cpuScaling() const { return mCpuScaling; }
      void setCpuScaling() { mCpuScaling = true; }
  
      bool truncateToSize() const { return mTruncateToSize; }
      void setTruncateToSize() { mTruncateToSize = true; }
  
      int fadvise() { return mFadvice; }
      void setFadvise(const char *advice);
      const char *fadviseAsStr() const;
  
      // Print the samples.
      void setDump() { StopWatch::setPrintRawMode(true); }
  
      StopWatch *testTimer() { return mTestTimer; }
      StopWatch *openTimer() { return mOpenTimer; }
      StopWatch *readTimer() { return mReadTimer; }
      StopWatch *writeTimer() { return mWriteTimer; }
      StopWatch *syncTimer() { return mSyncTimer; }
      StopWatch *truncateTimer() { return mTruncateTimer; }
  
      // Fork the children, run the test and wait for them to complete.
      bool runTest();
  
      void signalParentAndWait() {
          if (!android::writePidAndWaitForReply(mIpc[WRITE_TO_PARENT], mIpc[READ_FROM_PARENT])) {
              exit(1);
          }
      }
  
      void createTimers();
      bool setTypeFromName(const char *test_name);
      Type type() const { return mType; }
      pid_t pid() const { return mPid; }
      const char *name() const { return mName; }
  
      // This is set to the function that will actually do the test when
      // the command line arguments have been parsed. The function will
      // be run in one or more child(ren) process(es).
      bool (*mTestBody)(TestCase *);
  private:
      const char *mAppName;
      size_t mDataSize;
      size_t mChunkSize;
      size_t mIter;
      size_t mNproc;
      pid_t mPid;
      char mName[80];
      Type mType;
  
      bool mDump;  // print the raw values instead of a human friendly report.
      bool mCpuScaling;  // true, do not turn off cpu scaling.
      Sync mSync;
      int mFadvice;
      // When new files are created, truncate them to the final size.
      bool mTruncateToSize;
  
      bool mNewFairSleepers;
      bool mNormalizedSleepers;
  
      // IPC
      //        Parent               Child(ren)
      // ---------------------------------------
      // 0: read from child          closed
      // 1: closed                   write to parent
      // 2: closed                   read from parent
      // 3: write to child           closed
      int mIpc[4];
  
      StopWatch *mTestTimer;  // Used to time the test overall.
      StopWatch *mOpenTimer;  // Used to time the open calls.
      StopWatch *mReadTimer;  // Used to time the read calls.
      StopWatch *mWriteTimer;  // Used to time the write calls.
      StopWatch *mSyncTimer;  // Used to time the sync/fsync calls.
      StopWatch *mTruncateTimer;  // Used to time the ftruncate calls.
  };
  
  }  // namespace android_test
  
  #endif  // SYSTEM_EXTRAS_TESTS_SDCARD_TESTCASE_H_
  