• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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
13  *    distribution.
14  *
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
26  * SUCH DAMAGE.
27  */
28 
29 #include "testcase.h"
30 #include <hardware_legacy/power.h>  // wake lock
31 #include <sys/types.h>
32 #include <sys/wait.h>
33 #include <unistd.h>
34 #include <linux/fadvise.h>
35 
36 namespace {
37 const bool kVerbose = false;
38 }
39 
40 namespace android_test {
41 
TestCase(const char * appName)42 TestCase::TestCase(const char *appName)
43     : mTestBody(NULL), mAppName(appName), mDataSize(1000 * 1000),
44       mChunkSize(mDataSize), mTreeDepth(8), mIter(20), mNproc(1),
45       mType(UNKNOWN_TEST),  mDump(false), mCpuScaling(false),
46       mSync(NO_SYNC), mFadvice(POSIX_FADV_NORMAL), mTruncateToSize(false),
47       mTestTimer(NULL)
48 {
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);
54     mPid = getpid();
55     setNewFairSleepers(true);
56     setNormalizedSleepers(true);
57     if (pipe(mIpc) < 0)
58     {
59         fprintf(stderr, "pipe failed\n");
60         exit(1);
61     }
62     if (pipe(mIpc + 2) < 0)
63     {
64         fprintf(stderr, "pipe failed\n");
65         exit(1);
66     }
67 }
68 
~TestCase()69 TestCase::~TestCase()
70 {
71     release_wake_lock(mAppName);
72     for (int i = 0; i < 4; ++i) close(mIpc[i]);
73     delete mTestTimer;
74     delete mOpenTimer;
75 }
76 
77 
runTest()78 bool TestCase::runTest()
79 {
80     if (UNKNOWN_TEST == mType)
81     {
82         fprintf(stderr, "No test set.");
83         return false;
84     }
85     for (size_t p = 0; p < mNproc; ++p)
86     {
87         pid_t childpid = android::forkOrExit();
88 
89         if (0 == childpid) { // I am a child, run the test.
90             mPid = getpid();
91             close(mIpc[READ_FROM_CHILD]);
92             close(mIpc[WRITE_TO_CHILD]);
93 
94             if (kVerbose) printf("Child pid: %d\n", mPid);
95             if (!mTestBody(this)) {
96                 printf("Test failed\n");
97             }
98             char buffer[32000] = {0,};
99             char *str = buffer;
100             size_t size_left = sizeof(buffer);
101 
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);
108             if(traverseTimer()->used()) traverseTimer()->sprint(&str, &size_left);
109 
110             write(mIpc[TestCase::WRITE_TO_PARENT], buffer, str - buffer);
111 
112 
113             close(mIpc[WRITE_TO_PARENT]);
114             close(mIpc[READ_FROM_PARENT]);
115             exit(EXIT_SUCCESS);
116         }
117     }
118     // I am the parent process
119     close(mIpc[WRITE_TO_PARENT]);
120     close(mIpc[READ_FROM_PARENT]);
121 
122     // Block until all the children have reported for
123     // duty. Unblock them so they start the work.
124     if (!android::waitForChildrenAndSignal(mNproc, mIpc[READ_FROM_CHILD], mIpc[WRITE_TO_CHILD]))
125     {
126         exit(1);
127     }
128 
129     // Process the output of each child.
130     // TODO: handle EINTR
131     char buffer[32000] = {0,};
132     while(read(mIpc[READ_FROM_CHILD], buffer, sizeof(buffer)) != 0)
133     {
134         printf("%s", buffer);
135         fflush(stdout);
136         memset(buffer, 0, sizeof(buffer));
137     }
138     // Parent is waiting for children to exit.
139     android::waitForChildrenOrExit(mNproc);
140     return true;
141 }
142 
setIter(size_t iter)143 void TestCase::setIter(size_t iter)
144 {
145     mIter = iter;
146 }
147 
createTimers()148 void TestCase::createTimers()
149 {
150     char total_time[80];
151 
152     snprintf(total_time, sizeof(total_time), "%s_total", mName);
153     mTestTimer = new StopWatch(total_time, 1);
154     mTestTimer->setDataSize(dataSize());
155 
156     mOpenTimer = new StopWatch("open", iter() * kReadWriteFactor);
157 
158     mReadTimer = new StopWatch("read", iter() * dataSize() / chunkSize() * kReadWriteFactor);
159     mReadTimer->setDataSize(dataSize());
160 
161     mWriteTimer = new StopWatch("write", iter() * dataSize() / chunkSize());
162     mWriteTimer->setDataSize(dataSize());
163 
164     mSyncTimer = new StopWatch("sync", iter());
165 
166     mTruncateTimer = new StopWatch("truncate", iter());
167 
168     mTraverseTimer = new StopWatch("traversal", iter());
169 }
170 
setTypeFromName(const char * test_name)171 bool TestCase::setTypeFromName(const char *test_name)
172 {
173     strcpy(mName, test_name);
174     if (strcmp(mName, "write") == 0) mType = WRITE;
175     if (strcmp(mName, "read") == 0) mType = READ;
176     if (strcmp(mName, "read_write") == 0) mType = READ_WRITE;
177     if (strcmp(mName, "open_create") == 0) mType = OPEN_CREATE;
178     if (strcmp(mName, "traverse") == 0) mType = TRAVERSE;
179 
180     return UNKNOWN_TEST != mType;
181 }
182 
setSync(Sync s)183 void TestCase::setSync(Sync s)
184 {
185     mSync = s;
186 }
187 
syncAsStr() const188 const char *TestCase::syncAsStr() const
189 {
190     return mSync == NO_SYNC ? "disabled" : (mSync == FSYNC ? "fsync" : "sync");
191 }
192 
setFadvise(const char * advice)193 void TestCase::setFadvise(const char *advice)
194 {
195     mFadvice = POSIX_FADV_NORMAL;
196     if (strcmp(advice, "sequential") == 0)
197     {
198         mFadvice = POSIX_FADV_SEQUENTIAL;
199     }
200     else if (strcmp(advice, "random") == 0)
201     {
202         mFadvice = POSIX_FADV_RANDOM;
203     }
204     else if (strcmp(advice, "noreuse") == 0)
205     {
206         mFadvice = POSIX_FADV_NOREUSE;
207     }
208     else if (strcmp(advice, "willneed") == 0)
209     {
210         mFadvice = POSIX_FADV_WILLNEED;
211     }
212     else if (strcmp(advice, "dontneed") == 0)
213     {
214         mFadvice = POSIX_FADV_DONTNEED;
215     }
216 }
217 
fadviseAsStr() const218 const char *TestCase::fadviseAsStr() const
219 {
220     switch (mFadvice) {
221         case POSIX_FADV_NORMAL: return "fadv_normal";
222         case POSIX_FADV_SEQUENTIAL: return "fadv_sequential";
223         case POSIX_FADV_RANDOM: return "fadv_random";
224         case POSIX_FADV_NOREUSE: return "fadv_noreuse";
225         case POSIX_FADV_WILLNEED: return "fadv_willneed";
226         case POSIX_FADV_DONTNEED: return "fadv_dontneed";
227         default: return "fadvice_unknown";
228     }
229 }
230 
231 
232 }  // namespace android_test
233