2 * Copyright (C) 2009 The Android Open Source Project
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <hardware_legacy/power.h> // wake lock
31 #include <sys/types.h>
34 #include <linux/fadvise.h>
37 const bool kVerbose = false;
40 namespace android_test {
42 TestCase::TestCase(const char *appName)
43 : mTestBody(NULL), mAppName(appName), mDataSize(1000 * 1000),
44 mChunkSize(mDataSize), mIter(20), mNproc(1),
45 mType(UNKNOWN_TEST), mDump(false), mCpuScaling(false),
46 mSync(NO_SYNC), mFadvice(POSIX_FADV_NORMAL), mTruncateToSize(false),
49 // Make sure the cpu and phone are fully awake. The
50 // FULL_WAKE_LOCK was used by java apps and don't do
51 // anything. Also the partial wake lock is a nop if the phone
52 // is plugged in via USB.
53 acquire_wake_lock(PARTIAL_WAKE_LOCK, mAppName);
55 setNewFairSleepers(true);
56 setNormalizedSleepers(true);
59 fprintf(stderr, "pipe failed\n");
62 if (pipe(mIpc + 2) < 0)
64 fprintf(stderr, "pipe failed\n");
71 release_wake_lock(mAppName);
72 for (int i = 0; i < 4; ++i) close(mIpc[i]);
78 bool TestCase::runTest()
80 if (UNKNOWN_TEST == mType)
82 fprintf(stderr, "No test set.");
85 for (size_t p = 0; p < mNproc; ++p)
87 pid_t childpid = android::forkOrExit();
89 if (0 == childpid) { // I am a child, run the test.
91 close(mIpc[READ_FROM_CHILD]);
92 close(mIpc[WRITE_TO_CHILD]);
94 if (kVerbose) printf("Child pid: %d\n", mPid);
95 if (!mTestBody(this)) {
96 printf("Test failed\n");
98 char buffer[32000] = {0,};
100 size_t size_left = sizeof(buffer);
102 testTimer()->sprint(&str, &size_left);
103 if(openTimer()->used()) openTimer()->sprint(&str, &size_left);
104 if(readTimer()->used()) readTimer()->sprint(&str, &size_left);
105 if(writeTimer()->used()) writeTimer()->sprint(&str, &size_left);
106 if(syncTimer()->used()) syncTimer()->sprint(&str, &size_left);
107 if(truncateTimer()->used()) truncateTimer()->sprint(&str, &size_left);
109 write(mIpc[TestCase::WRITE_TO_PARENT], buffer, str - buffer);
112 close(mIpc[WRITE_TO_PARENT]);
113 close(mIpc[READ_FROM_PARENT]);
117 // I am the parent process
118 close(mIpc[WRITE_TO_PARENT]);
119 close(mIpc[READ_FROM_PARENT]);
121 // Block until all the children have reported for
122 // duty. Unblock them so they start the work.
123 if (!android::waitForChildrenAndSignal(mNproc, mIpc[READ_FROM_CHILD], mIpc[WRITE_TO_CHILD]))
128 // Process the output of each child.
129 // TODO: handle EINTR
130 char buffer[32000] = {0,};
131 while(read(mIpc[READ_FROM_CHILD], buffer, sizeof(buffer)) != 0)
133 printf("%s", buffer);
135 memset(buffer, 0, sizeof(buffer));
137 // Parent is waiting for children to exit.
138 android::waitForChildrenOrExit(mNproc);
142 void TestCase::setIter(size_t iter)
147 void TestCase::createTimers()
151 snprintf(total_time, sizeof(total_time), "%s_total", mName);
152 mTestTimer = new StopWatch(total_time, 1);
153 mTestTimer->setDataSize(dataSize());
155 mOpenTimer = new StopWatch("open", iter() * kReadWriteFactor);
157 mReadTimer = new StopWatch("read", iter() * dataSize() / chunkSize() * kReadWriteFactor);
158 mReadTimer->setDataSize(dataSize());
160 mWriteTimer = new StopWatch("write", iter() * dataSize() / chunkSize());
161 mWriteTimer->setDataSize(dataSize());
163 mSyncTimer = new StopWatch("sync", iter());
165 mTruncateTimer = new StopWatch("truncate", iter());
168 bool TestCase::setTypeFromName(const char *test_name)
170 strcpy(mName, test_name);
171 if (strcmp(mName, "write") == 0) mType = WRITE;
172 if (strcmp(mName, "read") == 0) mType = READ;
173 if (strcmp(mName, "read_write") == 0) mType = READ_WRITE;
174 if (strcmp(mName, "open_create") == 0) mType = OPEN_CREATE;
176 return UNKNOWN_TEST != mType;
179 void TestCase::setSync(Sync s)
184 const char *TestCase::syncAsStr() const
186 return mSync == NO_SYNC ? "disabled" : (mSync == FSYNC ? "fsync" : "sync");
189 void TestCase::setFadvise(const char *advice)
191 mFadvice = POSIX_FADV_NORMAL;
192 if (strcmp(advice, "sequential") == 0)
194 mFadvice = POSIX_FADV_SEQUENTIAL;
196 else if (strcmp(advice, "random") == 0)
198 mFadvice = POSIX_FADV_RANDOM;
200 else if (strcmp(advice, "noreuse") == 0)
202 mFadvice = POSIX_FADV_NOREUSE;
204 else if (strcmp(advice, "willneed") == 0)
206 mFadvice = POSIX_FADV_WILLNEED;
208 else if (strcmp(advice, "dontneed") == 0)
210 mFadvice = POSIX_FADV_DONTNEED;
214 const char *TestCase::fadviseAsStr() const
217 case POSIX_FADV_NORMAL: return "fadv_normal";
218 case POSIX_FADV_SEQUENTIAL: return "fadv_sequential";
219 case POSIX_FADV_RANDOM: return "fadv_random";
220 case POSIX_FADV_NOREUSE: return "fadv_noreuse";
221 case POSIX_FADV_WILLNEED: return "fadv_willneed";
222 case POSIX_FADV_DONTNEED: return "fadv_dontneed";
223 default: return "fadvice_unknown";
228 } // namespace android_test