From 52f1aa8a8a8e20ab7dfbbde01a46b3366f80c013 Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Thu, 21 Mar 2013 15:44:28 +0000 Subject: [PATCH] cache_check work --- .gitignore | 5 + Rakefile | 7 ++ cache/check.cc | 94 +++++++++++++++---- features/cache_check.feature | 76 +++++++++++++++ .../step_definitions/cache_check_steps.rb | 57 +++++++++++ features/support/aruba.rb | 1 - 6 files changed, 221 insertions(+), 19 deletions(-) create mode 100644 Rakefile create mode 100644 features/cache_check.feature create mode 100644 features/step_definitions/cache_check_steps.rb diff --git a/.gitignore b/.gitignore index 461031f..6d8198d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,14 @@ *_t *.d test.data + +thin_check thin_dump thin_restore thin_repair + +cache_check + *.metadata bad-metadata Makefile \ No newline at end of file diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..2c130ae --- /dev/null +++ b/Rakefile @@ -0,0 +1,7 @@ +require 'rubygems' +require 'cucumber' +require 'cucumber/rake/task' + +Cucumber::Rake::Task.new(:features) do |t| + t.cucumber_opts = "features --format progress" +end diff --git a/cache/check.cc b/cache/check.cc index 108310d..ad7d41c 100644 --- a/cache/check.cc +++ b/cache/check.cc @@ -17,21 +17,71 @@ // . #include +#include +#include +#include + +#include +#include #include #include +#include +#include +#include +#include -#if 0 -#include "array.h" -#include "metadata.h" -#include "metadata_checker.h" -#include "version.h" - -using namespace persistent_data; using namespace std; -using namespace thin_provisioning; + +//---------------------------------------------------------------- namespace { + struct stat guarded_stat(string const &path) { + struct stat info; + + int r = ::stat(path.c_str(), &info); + if (r) { + ostringstream msg; + char buffer[128], *ptr; + + ptr = ::strerror_r(errno, buffer, sizeof(buffer)); + msg << path << ": " << ptr; + throw runtime_error(msg.str()); + } + + return info; + } + + int open_file(string const &path, int mode) { + int fd = open(path.c_str(), mode); + if (fd < 0) { + ostringstream msg; + char buffer[128], *ptr; + + ptr = strerror_r(errno, buffer, sizeof(buffer)); + msg << path << ": " << ptr; + throw runtime_error(msg.str()); + } + + return fd; + } + int check(string const &path, bool quiet) { + struct stat info = guarded_stat(path); + + if (!S_ISREG(info.st_mode) && !S_ISBLK(info.st_mode)) { + ostringstream msg; + msg << path << ": " << "Not a block device or regular file"; + throw runtime_error(msg.str()); + } + + int fd = open_file(path, O_RDONLY); + + ostringstream msg; + msg << path << ": " << "No superblock found"; + throw runtime_error(msg.str()); + return 0; + +#if 0 try { metadata::ptr md(new metadata(path, metadata::OPEN)); @@ -48,6 +98,7 @@ namespace { } return 0; +#endif } void usage(ostream &out, string const &cmd) { @@ -57,8 +108,12 @@ namespace { << " {-h|--help}" << endl << " {-V|--version}" << endl; } + + char const *TOOLS_VERSION = "0.1.6"; } +//---------------------------------------------------------------- + int main(int argc, char **argv) { int c; @@ -82,7 +137,7 @@ int main(int argc, char **argv) break; case 'V': - cout << THIN_PROVISIONING_TOOLS_VERSION << endl; + cout << TOOLS_VERSION << endl; return 0; default: @@ -94,15 +149,18 @@ int main(int argc, char **argv) if (argc == optind) { cerr << "No input file provided." << endl; usage(cerr, basename(argv[0])); - exit(1); + return 1; } - return check(argv[optind], quiet); + try { + check(argv[optind], quiet); + + } catch (exception const &e) { + cerr << e.what() << endl; + return 1; + } + + return 0; } -#else -int main(int argc, char **argv) -{ - cerr << "not implemented" << endl; - return 1; -} -#endif + +//---------------------------------------------------------------- diff --git a/features/cache_check.feature b/features/cache_check.feature new file mode 100644 index 0000000..a2f4135 --- /dev/null +++ b/features/cache_check.feature @@ -0,0 +1,76 @@ +Feature: cache_check + Scenario: print version (-V flag) + When I run `cache_check -V` + + Then it should pass + And version to stdout + + Scenario: print version (--version flag) + When I run `cache_check --version` + + Then it should pass + And version to stdout + + Scenario: print help + When I run `cache_check --help` + + Then it should pass + And usage to stdout + + Scenario: print help + When I run `cache_check -h` + + Then it should pass + And usage to stdout + + Scenario: Metadata file must be specified + When I run `cache_check` + + Then it should fail + And usage to stderr + And the stderr should contain: + + """ + No input file provided. + """ + + Scenario: Metadata file doesn't exist + When I run `cache_check /arbitrary/filename` + + Then it should fail + And the stderr should contain: + """ + /arbitrary/filename: No such file or directory + """ + + Scenario: Metadata file cannot be a directory + Given a directory called foo + + When I run `cache_check foo` + + Then it should fail + And the stderr should contain: + """ + foo: Not a block device or regular file + """ + + Scenario: Metadata file exists, but can't be opened + Given input without read permissions + + When I run `cache_check input` + + Then it should fail + And the stderr should contain: + """ + input: Permission denied + """ + + Scenario: Metadata file full of zeroes + Given input file + And block 1 is zeroed + + When I run `cache_check input` + And the stderr should contain: + """ + input: No superblock found + """ \ No newline at end of file diff --git a/features/step_definitions/cache_check_steps.rb b/features/step_definitions/cache_check_steps.rb new file mode 100644 index 0000000..edba139 --- /dev/null +++ b/features/step_definitions/cache_check_steps.rb @@ -0,0 +1,57 @@ +DEFAULT_INPUT = 'input' +BLOCK_SIZE = 4096 + +Given /^a directory called (.*)\s*$/ do |dir| + create_dir(dir) +end + +Given /^input without read permissions$/ do + write_file(DEFAULT_INPUT, "\0" * 4096) + in_current_dir do + f = File.new(DEFAULT_INPUT) + f.chmod(0000) + end +end + +Given(/^input file$/) do + write_file(DEFAULT_INPUT, "\0" * BLOCK_SIZE * 1024) +end + +Given(/^block (\d+) is zeroed$/) do |b| + in_current_dir do + File.open(DEFAULT_INPUT, 'w') do |f| + f.seek(BLOCK_SIZE * b.to_i, IO::SEEK_SET) + f.write("\0" * BLOCK_SIZE) + end + end +end + +Then /^it should pass$/ do + assert_success(true) +end + +Then /^it should fail$/ do + assert_success(false) +end + +VERSION="0.1.6\n" + +Then /^version to stdout$/ do + assert_exact_output(VERSION, all_stdout) +end + +USAGE =<