cache_check work
This commit is contained in:
parent
81d4e5523f
commit
52f1aa8a8a
5
.gitignore
vendored
5
.gitignore
vendored
@ -3,9 +3,14 @@
|
|||||||
*_t
|
*_t
|
||||||
*.d
|
*.d
|
||||||
test.data
|
test.data
|
||||||
|
|
||||||
|
thin_check
|
||||||
thin_dump
|
thin_dump
|
||||||
thin_restore
|
thin_restore
|
||||||
thin_repair
|
thin_repair
|
||||||
|
|
||||||
|
cache_check
|
||||||
|
|
||||||
*.metadata
|
*.metadata
|
||||||
bad-metadata
|
bad-metadata
|
||||||
Makefile
|
Makefile
|
7
Rakefile
Normal file
7
Rakefile
Normal file
@ -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
|
94
cache/check.cc
vendored
94
cache/check.cc
vendored
@ -17,21 +17,71 @@
|
|||||||
// <http://www.gnu.org/licenses/>.
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#if 0
|
|
||||||
#include "array.h"
|
|
||||||
#include "metadata.h"
|
|
||||||
#include "metadata_checker.h"
|
|
||||||
#include "version.h"
|
|
||||||
|
|
||||||
using namespace persistent_data;
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace thin_provisioning;
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
namespace {
|
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) {
|
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 {
|
try {
|
||||||
metadata::ptr md(new metadata(path, metadata::OPEN));
|
metadata::ptr md(new metadata(path, metadata::OPEN));
|
||||||
|
|
||||||
@ -48,6 +98,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage(ostream &out, string const &cmd) {
|
void usage(ostream &out, string const &cmd) {
|
||||||
@ -57,8 +108,12 @@ namespace {
|
|||||||
<< " {-h|--help}" << endl
|
<< " {-h|--help}" << endl
|
||||||
<< " {-V|--version}" << endl;
|
<< " {-V|--version}" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char const *TOOLS_VERSION = "0.1.6";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
@ -82,7 +137,7 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
cout << THIN_PROVISIONING_TOOLS_VERSION << endl;
|
cout << TOOLS_VERSION << endl;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -94,15 +149,18 @@ int main(int argc, char **argv)
|
|||||||
if (argc == optind) {
|
if (argc == optind) {
|
||||||
cerr << "No input file provided." << endl;
|
cerr << "No input file provided." << endl;
|
||||||
usage(cerr, basename(argv[0]));
|
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
|
|
||||||
|
76
features/cache_check.feature
Normal file
76
features/cache_check.feature
Normal file
@ -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
|
||||||
|
"""
|
57
features/step_definitions/cache_check_steps.rb
Normal file
57
features/step_definitions/cache_check_steps.rb
Normal file
@ -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 =<<EOF
|
||||||
|
Usage: cache_check [options] {device|file}
|
||||||
|
Options:
|
||||||
|
{-q|--quiet}
|
||||||
|
{-h|--help}
|
||||||
|
{-V|--version}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
Then /^usage to stdout$/ do
|
||||||
|
assert_partial_output(USAGE, all_stdout)
|
||||||
|
end
|
||||||
|
|
||||||
|
Then /^usage to stderr$/ do
|
||||||
|
assert_partial_output(USAGE, all_stderr)
|
||||||
|
end
|
@ -1,4 +1,3 @@
|
|||||||
require 'aruba/cucumber'
|
require 'aruba/cucumber'
|
||||||
|
|
||||||
STDERR.puts "pwd = #{Dir::pwd}"
|
|
||||||
ENV['PATH'] = "#{Dir::pwd}:#{ENV['PATH']}"
|
ENV['PATH'] = "#{Dir::pwd}:#{ENV['PATH']}"
|
||||||
|
Loading…
Reference in New Issue
Block a user