sdcard_perf_test.cpp revision e1b480b11c19f014a2a6ceddd28883275a4ba0e3
14aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy/*
24aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * Copyright (C) 2009 The Android Open Source Project
34aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * All rights reserved.
44aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *
54aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * Redistribution and use in source and binary forms, with or without
64aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * modification, are permitted provided that the following conditions
74aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * are met:
84aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *  * Redistributions of source code must retain the above copyright
94aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *    notice, this list of conditions and the following disclaimer.
104aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *  * Redistributions in binary form must reproduce the above copyright
114aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *    notice, this list of conditions and the following disclaimer in
124aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *    the documentation and/or other materials provided with the
134aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *    distribution.
144aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy *
154aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
164aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
174aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
184aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19d5a85fb63d91a9297e8d9a11016f3b3ed60dfbabRomain Guy * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
209c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
219c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
224aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
239c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2413631f3da855f200a151e7837ed9f6b079622b58Romain Guy * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
254aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
264aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy * SUCH DAMAGE.
274aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy */
284aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy
29b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy#include <cstdio>
30b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy#include <cstdlib>
31b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy#include <ctime>
32ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include <errno.h>
33ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include <fcntl.h>
34ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include <getopt.h>
35ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include <limits.h>
36ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include <string.h>
37ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include <sys/stat.h>
38ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include <linux/fadvise.h>
39ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include <unistd.h>
40ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include <fts.h>
414cf6e2f34994f160e1baba205a43c12784dd3e0dRomain Guy
42ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include "stopwatch.h"
43ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include "sysutil.h"
44ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy#include "testcase.h"
45ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy
46ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// Stress test for the sdcard. Use this to generate some load on the
47ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// sdcard and collect performance statistics. The output is either a
48ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// human readable report or the raw timing samples that can be
49ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// processed using another tool.
505a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy//
51ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// Needs debugfs:
52ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy//   adb root;
53ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy//   adb shell mount -t debugfs none /sys/kernel/debug
5401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy//
5501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy// The following tests are defined (value of the --test flag):
56c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy//  write:       Open a file write some random data and close.
578b2f5267f16c295f12faab810527cd6311997e34Romain Guy//  read:        Open a file read it and close.
58ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy//  read_write:  Combine readers and writers.
59ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy//  open_create: Open|create an non existing file.
60ed6fcb034b44d9a6ac2fc72fee6030417811f234Romain Guy//
61ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// For each run you can control how many processes will run the test in
62325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy// parallel to simulate a real load (--procnb flag)
63eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy//
64ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// For each process, the test selected will be executed many time to
65ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// get a meaningful average/min/max (--iterations flag)
66ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy//
67ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// Use --dump to also get the raw data.
68ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy//
69daf98e941e140e8739458126640183b9f296a2abChet Haase// For read/write tests, size is the number of Kbytes to use.
705ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy//
715ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy// To build: mmm system/extras/tests/sdcard/Android.mk SDCARD_TESTS=1
72daf98e941e140e8739458126640183b9f296a2abChet Haase//
73ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// Examples:
74ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy// adb shell /system/bin/sdcard_perf_test --test=read --size=1000 --chunk-size=100 --procnb=1 --iterations=10 --dump > /tmp/data.txt
759c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase// adb shell /system/bin/sdcard_perf_test --test=write --size=1000 --chunk-size=100 --procnb=1 --iterations=100 --dump > /tmp/data.txt
769c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase//
779c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase// To watch the memory: cat /proc/meminfo
789c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase// If the phone crashes, look at /proc/last_kmsg on reboot.
799c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase//
8065b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy// TODO: It would be cool if we could play with various fadvise()
819c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase// strategies in here to see how tweaking read-ahead changes things.
8265b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy//
839c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase
849c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haaseextern char *optarg;
8565b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guyextern int optind, opterr, optopt;
8665b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy
8765b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy// TODO: No clue where fadvise is. Disabled for now.
8865b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy#define FADVISE(fd, off, len, advice) (void)0
8965b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy
9065b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy#ifndef min
919c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase#define min(a,b) (((a)>(b))?(b):(a))
929c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase#endif
939c1e23baf5bfbebd1aebbd6d9a18c225325567ceChet Haase
94491189f6bb81827a0c8e343f89420a9bcd2e62aeChet Haasenamespace  {
95491189f6bb81827a0c8e343f89420a9bcd2e62aeChet Haaseusing android::kernelVersion;
96491189f6bb81827a0c8e343f89420a9bcd2e62aeChet Haaseusing android::kMinKernelVersionBufferSize;
975977baa1fa24125c148a72699b53e62abaf08960Chet Haaseusing android::schedFeatures;
985977baa1fa24125c148a72699b53e62abaf08960Chet Haaseusing android::kMinSchedFeaturesBufferSize;
995977baa1fa24125c148a72699b53e62abaf08960Chet Haaseusing android_test::StopWatch;
1005977baa1fa24125c148a72699b53e62abaf08960Chet Haaseusing android::writePidAndWaitForReply;
101d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haaseusing android::waitForChildrenAndSignal;
102d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haaseusing android::waitForChildrenOrExit;
103d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haaseusing android_test::TestCase;
104a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
105a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haaseconst char *kAppName = "sdcard_perf_test";
106a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haaseconst char *kTestDir = "/sdcard/perf";
107a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haaseconst bool kVerbose = false;
108a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
109a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase// Used by getopt to parse the command line.
110a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haasestruct option long_options[] = {
111a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"size", required_argument, 0, 's'},
112a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"chunk-size", required_argument, 0, 'S'},
113a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"depth", required_argument, 0, 'D'},
114a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"iterations",  required_argument, 0, 'i'},
115a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"procnb",  required_argument, 0, 'p'},
116a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"test",  required_argument, 0, 't'},
117a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"dump",  no_argument, 0, 'd'},
118a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"cpu-scaling",  no_argument, 0, 'c'},
119a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"sync",  required_argument, 0, 'f'},
120a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"truncate", no_argument, 0, 'e'},
121a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"no-new-fair-sleepers", no_argument, 0, 'z'},
122a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"no-normalized-sleepers", no_argument, 0, 'Z'},
123a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"fadvise", required_argument, 0, 'a'},
124a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {"help", no_argument, 0, 'h'},
125a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {0, 0, 0, 0},
126a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase};
127a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
128a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haasevoid usage()
129a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase{
130a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    printf("sdcard_perf_test --test=write|read|read_write|open_create|traverse [options]\n\n"
131a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase           "  -t --test:        Select the test.\n"
132bb0acdf9e1d862a7cf0e2533321fc1105c29b5e3Romain Guy           "  -s --size:        Size in kbytes of the data.\n"
133bb0acdf9e1d862a7cf0e2533321fc1105c29b5e3Romain Guy           "  -S --chunk-size:  Size of a chunk. Default to size ie 1 chunk.\n"
134bb0acdf9e1d862a7cf0e2533321fc1105c29b5e3Romain Guy           "                    Data will be written/read using that chunk size.\n"
135bb0acdf9e1d862a7cf0e2533321fc1105c29b5e3Romain Guy           "  -D --depth:       Depth of directory tree to create for traversal.\n",
136bb0acdf9e1d862a7cf0e2533321fc1105c29b5e3Romain Guy           "  -i --iterations:  Number of time a process should carry its task.\n"
137bb0acdf9e1d862a7cf0e2533321fc1105c29b5e3Romain Guy           "  -p --procnb:      Number of processes to use.\n"
138bb0acdf9e1d862a7cf0e2533321fc1105c29b5e3Romain Guy           "  -d --dump:        Print the raw timing on stdout.\n"
139d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haase           "  -c --cpu-scaling: Enable cpu scaling.\n"
1405977baa1fa24125c148a72699b53e62abaf08960Chet Haase           "  -s --sync: fsync|sync Use fsync or sync in write test. Default: no sync call.\n"
1415977baa1fa24125c148a72699b53e62abaf08960Chet Haase           "  -e --truncate:    Truncate to size the file on creation.\n"
142866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase           "  -z --no-new-fair-sleepers: Turn them off. You need to mount debugfs.\n"
143866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase           "  -Z --no-normalized-sleepers: Turn them off. You need to mount debugfs.\n"
144866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase           "  -a --fadvise:     Specify an fadvise policy (not supported).\n"
145866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase           );
146866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase}
147866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase
148866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase// Print command line, pid, kernel version, OOM adj and scheduler.
149866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haasevoid printHeader(int argc, char **argv, const TestCase& testCase)
150866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase{
151866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase    printf("# Command: ");
152866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase    for (int i = 0; i < argc; ++i)
153866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase    {
154866ed817d0adf5b874eff277b4a4d2bcc6f61830Chet Haase        printf("%s ", argv[i]);
155a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    }
156a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    printf("\n");
1575977baa1fa24125c148a72699b53e62abaf08960Chet Haase
1585977baa1fa24125c148a72699b53e62abaf08960Chet Haase    printf("# Pid: %d\n", getpid());
1595977baa1fa24125c148a72699b53e62abaf08960Chet Haase
1605977baa1fa24125c148a72699b53e62abaf08960Chet Haase    {
1615977baa1fa24125c148a72699b53e62abaf08960Chet Haase        char buffer[kMinKernelVersionBufferSize] = {0, };
1625977baa1fa24125c148a72699b53e62abaf08960Chet Haase        if (kernelVersion(buffer, sizeof(buffer)) > 0)
1635977baa1fa24125c148a72699b53e62abaf08960Chet Haase        {
164d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy            printf("# Kernel: %s", buffer);
165d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy        }
166d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy    }
167d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy
168d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy    // Earlier on, running this test was crashing the phone. It turned
16924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    // out that it was using too much memory but its oom_adj value was
17043ccf4663c822ddd435b7683cc05221f6169c6c3Romain Guy    // -17 which means disabled. -16 is the system_server and 0 is
171d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy    // typically what applications run at. The issue is that adb runs
1725977baa1fa24125c148a72699b53e62abaf08960Chet Haase    // at -17 and so is this test. We force oom_adj to 0 unless the
17324c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy    // oom_adj option has been used.
1745977baa1fa24125c148a72699b53e62abaf08960Chet Haase    // TODO: We talked about adding an option to control oom_adj, not
1755977baa1fa24125c148a72699b53e62abaf08960Chet Haase    // sure if we still need that.
1765977baa1fa24125c148a72699b53e62abaf08960Chet Haase    int oomAdj = android::pidOutOfMemoryAdj();
1775977baa1fa24125c148a72699b53e62abaf08960Chet Haase
1785977baa1fa24125c148a72699b53e62abaf08960Chet Haase    printf("# Oom_adj: %d ", oomAdj);
1795977baa1fa24125c148a72699b53e62abaf08960Chet Haase    if (oomAdj < 0)
1802fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy    {
1811af23a32d879db330eb5a08b21090ec60b604a32Romain Guy        android::setPidOutOfMemoryAdj(0);
1821af23a32d879db330eb5a08b21090ec60b604a32Romain Guy        printf("adjuted to %d", android::pidOutOfMemoryAdj());
1831af23a32d879db330eb5a08b21090ec60b604a32Romain Guy    }
1842fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy    printf("\n");
1852fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy
1862fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy    {
1875977baa1fa24125c148a72699b53e62abaf08960Chet Haase        char buffer[kMinSchedFeaturesBufferSize] = {0, };
1885977baa1fa24125c148a72699b53e62abaf08960Chet Haase        if (schedFeatures(buffer, sizeof(buffer)) > 0)
1895977baa1fa24125c148a72699b53e62abaf08960Chet Haase        {
1905977baa1fa24125c148a72699b53e62abaf08960Chet Haase            printf("# Sched features: %s", buffer);
1915977baa1fa24125c148a72699b53e62abaf08960Chet Haase        }
1925977baa1fa24125c148a72699b53e62abaf08960Chet Haase    }
193d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haase    printf("# Fadvise: %s\n", testCase.fadviseAsStr());
194b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy}
195b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
196b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy// Remove all the files under kTestDir and clear the caches.
197b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guyvoid cleanup() {
198b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    android::resetDirectory(kTestDir);
199b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    android::syncAndDropCaches();  // don't pollute runs.
200b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy}
201d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haase
202d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haase// @param argc, argv have a wild guess.
203d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haase// @param[out] testCase Structure built from the cmd line args.
204d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haasevoid parseCmdLine(int argc, char **argv, TestCase *testCase)\
205a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase{
206d63cbd10765e8f48e39b07b15f0a4b70bf853ec8Chet Haase    int c;
20765b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy
20865b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy    while(true)
209b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy    {
21065b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy        // getopt_long stores the option index here.
211b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        int option_index = 0;
2125c13d89c1332fcc499379b9064b891187b75ca32Chet Haase
213b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy        c = getopt_long (argc, argv,
2145c13d89c1332fcc499379b9064b891187b75ca32Chet Haase                         "hS:s:D:i:p:t:dcf:ezZa:",
2155c13d89c1332fcc499379b9064b891187b75ca32Chet Haase                         long_options,
2165c13d89c1332fcc499379b9064b891187b75ca32Chet Haase                         &option_index);
2175c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        // Detect the end of the options.
2185c13d89c1332fcc499379b9064b891187b75ca32Chet Haase        if (c == -1) break;
219b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy
220d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase        switch (c)
221d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy        {
222d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy            case 's':
223d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy                testCase->setDataSize(atoi(optarg) * 1024);
224d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy                break;
225d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy            case 'S':
226d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy                testCase->setChunkSize(atoi(optarg) * 1024);
227d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy                break;
22824c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy            case 'D': // tree depth
22924c00216687ac87fe531dc4d4168ac0c0ca04ea6Romain Guy                testCase->setTreeDepth(atoi(optarg));
230d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy                break;
231d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy            case 'i':
232d586ad9c9fec80aa1d24d6b53cd2c8d5b47fe868Romain Guy                testCase->setIter(atoi(optarg));
233b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy                printf("# Iterations: %d\n", testCase->iter());
234b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy                break;
235d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase            case 'p':
236d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase                testCase->setNproc(atoi(optarg));
237d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase                printf("# Proc nb: %d\n", testCase->nproc());
238d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase                break;
239d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase            case 't':
2402fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy                testCase->setTypeFromName(optarg);
2412fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy                printf("# Test name %s\n", testCase->name());
2422fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy                break;
2432fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy            case 'd':
2442fc941e4650d618ff6e122f28b616d9032ffa134Romain Guy                testCase->setDump();
245d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase                break;
246d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase            case 'c':
247d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase                printf("# Cpu scaling is on\n");
248d98aa2de9ab18e09c2be1997f41212740f51f6e6Chet Haase                testCase->setCpuScaling();
249b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy                break;
250b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy            case 'f':
251b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy                if (strcmp("sync", optarg) == 0) {
25265b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy                    testCase->setSync(TestCase::SYNC);
25304c9d8c2ffd028c35c750bac0a4a7b79e48059b5Romain Guy                } else if (strcmp("fsync", optarg) == 0) {
25465b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy                    testCase->setSync(TestCase::FSYNC);
25565b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy                }
25665b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy                break;
25765b345fa22b878e141b8fd8ece9c208df00fa40fRomain Guy            case 'e':  // e for empty
258b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy                printf("# Will truncate to size\n");
259b051e895ccb696604349c6c5efe7c4747e1d1ab6Romain Guy                testCase->setTruncateToSize();
260ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                break;
261ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            case 'z':  // no new fair sleepers
262ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                testCase->setNewFairSleepers(false);
263ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                break;
264ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            case 'Z':  // no normalized sleepers
265ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                testCase->setNormalizedSleepers(false);
266ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                break;
267ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            case 'a':  // fadvise
268ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                testCase->setFadvise(optarg);
269ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                break;
270ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            case 'h':
271ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                usage();
272ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                exit(0);
27313631f3da855f200a151e7837ed9f6b079622b58Romain Guy            default:
274ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                fprintf(stderr, "Unknown option %s\n", optarg);
275ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                exit(EXIT_FAILURE);
276ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        }
277a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    }
278ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase}
279ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
280ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// ----------------------------------------------------------------------
281ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// READ TEST
28233f6beb10f98e8ba96250e284876d607055d278dRomain Guy
28333f6beb10f98e8ba96250e284876d607055d278dRomain Guy// Read a file.  We use a new file each time to avoid any caching
28433f6beb10f98e8ba96250e284876d607055d278dRomain Guy// effect that would happen if we were reading the same file each
28533f6beb10f98e8ba96250e284876d607055d278dRomain Guy// time.
286a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase// @param chunk buffer large enough where the chunk read are written.
287ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// @param idx iteration number.
288ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// @param testCase has all the timers and paramters to run the test.
289ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
290ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haasebool readData(char *const chunk, const int idx, TestCase *testCase)
2915baa3a62a97544669fba6d65a11c07f252e654ddSteve Block{
292ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    char filename[80] = {'\0',};
293ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
294ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    sprintf(filename, "%s/file-%d-%d", kTestDir, idx, getpid());
295ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
2965baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    testCase->openTimer()->start();
297ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    int fd = open(filename, O_RDONLY);
298ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    testCase->openTimer()->stop();
299ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
3005baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    if (fd < 0)
301ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
302ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        fprintf(stderr, "Open read only failed.");
303ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        return false;
304ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
3055baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    FADVISE(fd, 0, 0, testCase->fadvise());
306ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
307ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    size_t left = testCase->dataSize();
308ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    pid_t *pid = (pid_t*)chunk;
309ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    while (left > 0)
310ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
311ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        char *dest = chunk;
312ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        size_t chunk_size = testCase->chunkSize();
3135ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy
314ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        if (chunk_size > left)
3155baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        {
316a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            chunk_size = left;
317ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            left = 0;
318ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        }
319ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        else
320ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        {
321ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            left -= chunk_size;
322ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        }
323ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
324ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        testCase->readTimer()->start();
325ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        while (chunk_size > 0)
3265baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        {
327a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            ssize_t s = read(fd, dest, chunk_size);
328ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            if (s < 0)
329ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            {
330ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                fprintf(stderr, "Failed to read.\n");
331ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                close(fd);
332ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                return false;
3335baa3a62a97544669fba6d65a11c07f252e654ddSteve Block            }
334ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            chunk_size -= s;
335ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            dest += s;
336ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        }
337ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        testCase->readTimer()->stop();
3385baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    }
339ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    close(fd);
340ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    if (testCase->pid() != *pid)
341ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
342ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        fprintf(stderr, "Wrong pid found @ read block %x != %x\n", testCase->pid(), *pid);
343ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        return false;
3445baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    }
345ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    else
346ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
347ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        return true;
348ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
349ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase}
3505baa3a62a97544669fba6d65a11c07f252e654ddSteve Block
351ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
352ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haasebool testRead(TestCase *testCase) {
353ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    // Setup the testcase by writting some dummy files.
354ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    const size_t size = testCase->dataSize();
3555baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    size_t chunk_size = testCase->chunkSize();
356ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    char *const chunk = new char[chunk_size];
357ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
358ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    memset(chunk, 0xaa, chunk_size);
359ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    *((pid_t *)chunk) = testCase->pid(); // write our pid at the beginning of each chunk
360a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
361a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    size_t iter = testCase->iter();
362a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
363a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    // since readers are much faster we increase the number of
364ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    // iteration to last longer and have concurrent read/write
365ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    // thoughout the whole test.
366ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    if (testCase->type() == TestCase::READ_WRITE)
367ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
368ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        iter *= TestCase::kReadWriteFactor;
369ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
370ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
371ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    for (size_t i = 0; i < iter; ++i)
3725baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    {
373a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        char filename[80] = {'\0',};
374ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
375ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        sprintf(filename, "%s/file-%d-%d", kTestDir, i, testCase->pid());
376ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        int fd = open(filename, O_RDWR | O_CREAT, S_IRWXU);
377ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
378ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        size_t left = size;
379ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        while (left > 0)
38033f6beb10f98e8ba96250e284876d607055d278dRomain Guy        {
38133f6beb10f98e8ba96250e284876d607055d278dRomain Guy            if (chunk_size > left)
382a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            {
383ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                chunk_size = left;
384ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            }
385ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            ssize_t written = write(fd, chunk, chunk_size);
386ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            if (written < 0)
387ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            {
388ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                fprintf(stderr, "Write failed %d %s.", errno, strerror(errno));
389ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                return false;
3905ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy            }
3915baa3a62a97544669fba6d65a11c07f252e654ddSteve Block            left -= written;
392a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        }
393ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        close(fd);
394ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
395ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    if (kVerbose) printf("Child %d all chunk written\n", testCase->pid());
396ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
397ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    android::syncAndDropCaches();
398ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    testCase->signalParentAndWait();
3995ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy
4005baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    // Start the read test.
401a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    testCase->testTimer()->start();
402ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    for (size_t i = 0; i < iter; ++i)
403ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
404ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        if (!readData(chunk, i, testCase))
405ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        {
406ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            return false;
4075ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        }
4085baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    }
409a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    testCase->testTimer()->stop();
410ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
411ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    delete [] chunk;
412ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    return true;
413ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase}
414ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
415ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// ----------------------------------------------------------------------
416ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// WRITE TEST
417ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
418ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haasebool writeData(const char *const chunk, const int idx, TestCase *testCase) {
419ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    char filename[80] = {'\0',};
420ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
421ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    sprintf(filename, "%s/file-%d-%d", kTestDir, idx, getpid());
4225ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    testCase->openTimer()->start();
4235baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    int fd = open(filename, O_RDWR | O_CREAT, S_IRWXU);  // no O_TRUNC, see header comment
424a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    testCase->openTimer()->stop();
425ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
426ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    if (fd < 0)
427ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
428ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        fprintf(stderr, "Open write failed.");
429ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        return false;
430ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
431ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    FADVISE(fd, 0, 0, testCase->fadvise());
432ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
433ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    if (testCase->truncateToSize())
434ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
435ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        testCase->truncateTimer()->start();
4365ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        ftruncate(fd, testCase->dataSize());
4375baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        testCase->truncateTimer()->stop();
438ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
439ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
440ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    size_t left = testCase->dataSize();
441ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    while (left > 0)
442ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
443ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        const char *dest = chunk;
444ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        size_t chunk_size = testCase->chunkSize();
445ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
446ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        if (chunk_size > left)
447ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        {
448ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            chunk_size = left;
449ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            left = 0;
450ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        }
451a62f172215727a1e00af0cb934904e00926a86c9Romain Guy        else
452a62f172215727a1e00af0cb934904e00926a86c9Romain Guy        {
453a62f172215727a1e00af0cb934904e00926a86c9Romain Guy            left -= chunk_size;
454a62f172215727a1e00af0cb934904e00926a86c9Romain Guy        }
4555ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy
4565baa3a62a97544669fba6d65a11c07f252e654ddSteve Block
457a62f172215727a1e00af0cb934904e00926a86c9Romain Guy        testCase->writeTimer()->start();
458ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        while (chunk_size > 0)
459ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        {
460ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            ssize_t s = write(fd, dest, chunk_size);
461ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            if (s < 0)
462ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            {
4635baa3a62a97544669fba6d65a11c07f252e654ddSteve Block                fprintf(stderr, "Failed to write.\n");
464ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                close(fd);
465ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                return false;
466ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            }
467ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            chunk_size -= s;
468ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            dest += s;
469ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        }
470ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        testCase->writeTimer()->stop();
4715ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    }
4725baa3a62a97544669fba6d65a11c07f252e654ddSteve Block
473a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    if (TestCase::FSYNC == testCase->sync())
474ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
475ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        testCase->syncTimer()->start();
476ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        fsync(fd);
477ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        testCase->syncTimer()->stop();
478ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
479ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    else if (TestCase::SYNC == testCase->sync())
480ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
481ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        testCase->syncTimer()->start();
482ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        sync();
4835ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        testCase->syncTimer()->stop();
4845baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    }
485a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    close(fd);
486ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    return true;
487ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase}
488ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
489ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haasebool testWrite(TestCase *testCase)
490ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase{
491ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    const size_t size = testCase->dataSize();
4925ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    size_t chunk_size = testCase->chunkSize();
4935baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    char *data = new char[chunk_size];
494a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
495ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    memset(data, 0xaa, chunk_size);
496ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    // TODO: write the pid at the beginning like in the write
497ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    // test. Have a mode where we check the write was correct.
498ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    testCase->signalParentAndWait();
499ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
500ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    testCase->testTimer()->start();
501ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    for (size_t i = 0; i < testCase->iter(); ++i)
5025ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    {
5035baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        if (!writeData(data, i, testCase))
504a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        {
505ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            return false;
506ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        }
507ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
508ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    testCase->testTimer()->stop();
509ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    delete [] data;
510ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    return true;
511ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase}
512ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
513ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
514ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// ----------------------------------------------------------------------
5155ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy// READ WRITE
5165baa3a62a97544669fba6d65a11c07f252e654ddSteve Block
517a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase// Mix of read and write test. Even PID run the write test. Odd PID
518ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// the read test. Not fool proof but work most of the time.
519ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haasebool testReadWrite(TestCase *testCase)
520ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase{
521ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    if (getpid() & 0x1) {
5225ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        return testRead(testCase);
5235baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    } else {
524ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        return testWrite(testCase);
525ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
526ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase}
527ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
528ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// ----------------------------------------------------------------------
5295ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy// OPEN CREATE TEST
5305baa3a62a97544669fba6d65a11c07f252e654ddSteve Block
531ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haasebool testOpenCreate(TestCase *testCase)
532ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase{
533ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    char filename[80] = {'\0',};
534ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
535ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    testCase->signalParentAndWait();
5365ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    testCase->testTimer()->start();
5375baa3a62a97544669fba6d65a11c07f252e654ddSteve Block
538ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    for (size_t i = 0; i < testCase->iter(); ++i)
539ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    {
540ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        sprintf(filename, "%s/file-%d-%d", kTestDir, i, testCase->pid());
541ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
542325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        int fd = open(filename, O_RDWR | O_CREAT, S_IRWXU);
543ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        FADVISE(fd, 0, 0, testCase->fadvise());
544ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
5455ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy        if (testCase->truncateToSize())
546cac5fd3e09e9dc918753d4aff624bf29a367ade3Romain Guy        {
5475baa3a62a97544669fba6d65a11c07f252e654ddSteve Block            ftruncate(fd, testCase->dataSize());
548a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        }
549ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        if (fd < 0)
550ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        {
551325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy            return false;
552325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        }
553325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy        close(fd);
554325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy    }
555325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy    testCase->testTimer()->stop();
556325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy    return true;
557325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy}
558325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy
559325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guybool writeTestFile(TestCase *testCase, const char* filename) {
560325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy    int fd = open(filename, O_RDWR | O_CREAT, S_IRWXU);
561325740fb444af8fc7fb0119b2e30ce322c2ae134Romain Guy    if (fd < 0) {
562eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        fprintf(stderr, "open() failed: %s\n", strerror(errno));
563eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy        return false;
564eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy    }
565eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy
566eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy    bool res = false;
5675ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy
568eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy    char * const chunk = new char[testCase->chunkSize()];
569a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    memset(chunk, 0xaa, testCase->chunkSize());
570eb9a5367e8f0e970db8509ffb2584f5376bc62edRomain Guy
571ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    size_t left = testCase->dataSize();
5725baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    while (left > 0) {
573ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        char *dest = chunk;
574ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        size_t chunk_size = testCase->chunkSize();
575ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
576ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        if (chunk_size > left) {
5775baa3a62a97544669fba6d65a11c07f252e654ddSteve Block            chunk_size = left;
578ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            left = 0;
579ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        } else {
580ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            left -= chunk_size;
5815baa3a62a97544669fba6d65a11c07f252e654ddSteve Block        }
582ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
583ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        while (chunk_size > 0) {
584ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            ssize_t s = write(fd, dest, chunk_size);
585ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            if (s < 0) {
5865baa3a62a97544669fba6d65a11c07f252e654ddSteve Block                fprintf(stderr, "write() failed: %s\n", strerror(errno));
587ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase                goto fail;
588ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            }
589ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            chunk_size -= s;
5905baa3a62a97544669fba6d65a11c07f252e654ddSteve Block            dest += s;
591ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        }
592ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    }
593ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
594ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    res = true;
595ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haasefail:
596ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    close(fd);
597ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    delete[] chunk;
5985baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    return res;
599a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase}
600ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
601ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase// ----------------------------------------------------------------------
6025ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy// TRAVERSE
6035ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy
6045ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy#define MAX_PATH 512
6055ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy
6065ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy// Creates a directory tree that is both deep and wide, and times
6075ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy// traversal using fts_open().
6085ff9df658230d49e42c43586997a02d8e4dd417eRomain Guybool testTraverse(TestCase *testCase) {
6095ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    char path[MAX_PATH];
6105ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    char filepath[MAX_PATH];
6115ff9df658230d49e42c43586997a02d8e4dd417eRomain Guy    strcpy(path, kTestDir);
612ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase
6135baa3a62a97544669fba6d65a11c07f252e654ddSteve Block    // Generate a deep directory hierarchy
614a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    size_t depth = testCase->treeDepth();
615ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase    for (size_t i = 0; i < depth; i++) {
616ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        // Go deeper by appending onto current path
617ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase        snprintf(path + strlen(path), MAX_PATH - strlen(path), "/dir%d", i);
618a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        mkdir(path, S_IRWXU);
619a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
620a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        // Create some files at this depth
621a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        strcpy(filepath, path);
622a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        int pathlen = strlen(path);
623a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        char* nameStart = filepath + pathlen;
624a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        for (size_t j = 0; j < depth; j++) {
625a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            snprintf(nameStart, MAX_PATH - pathlen, "/file%d", j);
626a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            writeTestFile(testCase, filepath);
627a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        }
628a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    }
629a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
630a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    testCase->signalParentAndWait();
631a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    testCase->testTimer()->start();
632a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
633a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    // Now traverse structure
634a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    size_t iter = testCase->iter();
635a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    for (size_t i = 0; i < iter; i++) {
636a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        testCase->traverseTimer()->start();
637a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
638a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        FTS *ftsp;
639a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        if ((ftsp = fts_open((char **) &kTestDir, FTS_LOGICAL | FTS_XDEV, NULL)) == NULL) {
640a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            fprintf(stderr, "fts_open() failed: %s\n", strerror(errno));
641a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            return false;
642a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        }
643a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
644a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        // Count discovered files
645a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        int dirs = 0, files = 0;
646a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
647a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        FTSENT *curr;
648a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        while ((curr = fts_read(ftsp)) != NULL) {
649a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            switch (curr->fts_info) {
650a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            case FTS_D:
651a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase                dirs++;
652a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase                break;
653a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            case FTS_F:
654a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase                files++;
655a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase                break;
656a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            }
657a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        }
658a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
659a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        fts_close(ftsp);
660a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
661a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        testCase->traverseTimer()->stop();
662a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
663a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        int expectedDirs = depth + 1;
664a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        if (expectedDirs != dirs) {
665a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            fprintf(stderr, "expected %d dirs, but found %d\n", expectedDirs, dirs);
666a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            return false;
667a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        }
668a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
669a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        int expectedFiles = depth * depth;
670a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        if (expectedFiles != files) {
671a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            fprintf(stderr, "expected %d files, but found %d\n", expectedFiles, files);
672a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            return false;
673a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        }
674a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    }
675a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
676a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    testCase->testTimer()->stop();
677a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    return true;
678a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase}
679a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
680a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase}  // anonymous namespace
681a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
682a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haaseint main(int argc, char **argv)
683a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase{
684a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    android_test::TestCase testCase(kAppName);
685a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
686a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    cleanup();
687a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
688a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    parseCmdLine(argc, argv, &testCase);
689a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    printHeader(argc, argv, testCase);
690a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
691a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    printf("# File size %d kbytes\n", testCase.dataSize() / 1024);
692a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    printf("# Chunk size %d kbytes\n", testCase.chunkSize() / 1024);
693a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    printf("# Sync: %s\n", testCase.syncAsStr());
694a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
695a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    if (!testCase.cpuScaling())
696a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {
697a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        android::disableCpuScaling();
698a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    }
699a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
700a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    switch(testCase.type()) {
701a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        case TestCase::WRITE:
702a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            testCase.mTestBody = testWrite;
703a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            break;
704a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        case TestCase::READ:
705ed30fd8e9a2d65ee5c8520de55b0089c219f390cChet Haase            testCase.mTestBody = testRead;
706a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            break;
707a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        case TestCase::OPEN_CREATE:
708a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            testCase.mTestBody = testOpenCreate;
709a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            break;
710a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        case TestCase::READ_WRITE:
711a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            testCase.mTestBody = testReadWrite;
712a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            break;
713a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        case TestCase::TRAVERSE:
714a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            testCase.mTestBody = testTraverse;
715a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            break;
716a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        default:
717a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            fprintf(stderr, "Unknown test type %s", testCase.name());
718a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase            exit(EXIT_FAILURE);
719a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    }
720a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
721a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    testCase.createTimers();
722a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
723a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    bool ok;
724a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
725a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    ok = testCase.runTest();
726a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase
727a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    cleanup();
728a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    if (!ok)
729a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {
730a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        printf("error %d %s", errno, strerror(errno));
731a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        exit(EXIT_FAILURE);
732a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    }
733a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    else
734a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    {
735a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase        exit(EXIT_SUCCESS);
736a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase    }
737a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase}
738a1cff5043d0fbd78fcf9c48e7658e56a5b0c2de3Chet Haase