blob: cc6015081b9c15155f1a678ef4bce82241fc790f [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fbl/string.h>
#include <fs-test-utils/blobfs/bloblist.h>
#include <zircon/assert.h>
#include <stdio.h>
namespace {
constexpr char kUsage[] = R"(
Usage:
%s <seed> <mount-point> <num-ops>
Performs random operations on a blobfs partition until killed. The blobfs partition should be
mounted at the provided mount point, and already formatted. The operations will be additive
(it won't delete files that are already there).
[Required Arguments]
seed An unsigned integer to initialize pseudo-random number generator.
mount-point Path to a mounted blobfs partition bound in this program's namespace.
Must be mounted read/write.
num-ops Number of operations to perform. If 0 is provided, it will perform
infinite operations. The combination of a provided seed and num-ops
will produce deterministic behavior.
)";
void PrintUsage(const char* arg0) { printf(kUsage, arg0); }
bool ParseCommandLineArgs(int argc, const char* const* argv, unsigned int* seed,
fbl::String* mount_point, unsigned int* num_ops) {
if (argc != 4) {
printf("missing (or too many?) arguments.\n");
PrintUsage(argv[0]);
return false;
}
*seed = static_cast<unsigned int>(strtoul(argv[1], NULL, 0));
*mount_point = fbl::String(argv[2]);
*num_ops = static_cast<unsigned int>(strtoul(argv[3], NULL, 0));
return true;
}
bool GenerateLoad(unsigned int seed, fbl::String mount_point, unsigned int num_ops) {
printf("performing random operations on provided partition...\n");
fs_test_utils::BlobList blob_list(mount_point);
unsigned int ops_performed = 0;
while (num_ops == 0 || ops_performed++ < num_ops) {
switch (rand_r(&seed) % 6) {
case 0:
ZX_ASSERT(blob_list.CreateBlob(&seed));
break;
case 1:
ZX_ASSERT(blob_list.ConfigBlob());
break;
case 2:
// ZX-4689 - it's possible that we will run out of space on this or the truncate. If we
// do, this errors out.
ZX_ASSERT(blob_list.WriteData());
break;
case 3:
ZX_ASSERT(blob_list.ReadData());
break;
case 4:
ZX_ASSERT(blob_list.ReopenBlob());
break;
case 5:
ZX_ASSERT(blob_list.UnlinkBlob());
break;
default:
// changed the number of possible operations and didn't add another case branch.
ZX_ASSERT(false);
break;
}
}
return true;
}
} // namespace
int main(int argc, char** argv) {
unsigned int seed, num_ops;
fbl::String mount_point;
if (!ParseCommandLineArgs(argc, argv, &seed, &mount_point, &num_ops)) {
return -1;
}
return GenerateLoad(seed, mount_point, num_ops) ? 0 : -1;
}