validations 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/validations.rb +4 -0
- data/lib/validations/index_validations.rb +113 -0
- data/lib/validations/version.rb +3 -0
- data/spec/validations/index_validations_spec.rb +100 -0
- metadata +114 -0
data/lib/validations.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'params'
|
2
|
+
require 'log'
|
3
|
+
require 'content_data'
|
4
|
+
require 'file_indexing/index_agent'
|
5
|
+
|
6
|
+
# TODO additional params?
|
7
|
+
# TODO are params names good enough?
|
8
|
+
module Validations
|
9
|
+
class IndexValidations
|
10
|
+
|
11
|
+
# TODO should it be renamed cause it can validate any indexes, not specially remote, one against another.
|
12
|
+
|
13
|
+
# Validates remote index against local file system.
|
14
|
+
# Remote index defined valid when every remote content has at least one valid local instance.
|
15
|
+
#
|
16
|
+
# There are two levels of validation, controlled by instance_check_level system parameter:
|
17
|
+
# * shallow - quick, tests instance for file existence and attributes.
|
18
|
+
# * deep - can take more time, in addition to shallow recalculates hash sum.
|
19
|
+
# For more infoemation see <tt>ContentData</tt> documentation.
|
20
|
+
# @param [ContentData] remote_index it's contents should be validate against local index
|
21
|
+
# @param [ContentData] local_index contains local contents and instances used for validation
|
22
|
+
# @param [Hash] params hash of parameters of validation, can be used to return additional data
|
23
|
+
#
|
24
|
+
# Supported key/value combinations:
|
25
|
+
# * key is <tt>:failed</tt> value is <tt>ContentData</tt> used to return failed instances
|
26
|
+
# @return [Boolean] true when every remote content has at least one valid local instance, false otherwise
|
27
|
+
# @raise [ArgumentError] when instance_check_level is incorrect
|
28
|
+
def IndexValidations.validate_remote_index(remote_index, local_index, params = nil)
|
29
|
+
raise ArgumentError 'remote_index must be defined' if remote_index.nil?
|
30
|
+
raise ArgumentError 'local index must be defined' if local_index.nil?
|
31
|
+
|
32
|
+
# used to answer whether specific param was set
|
33
|
+
param_exists = Proc.new do |param|
|
34
|
+
!(params.nil? || params[param].nil?)
|
35
|
+
end
|
36
|
+
|
37
|
+
# used to process method parameters centrally
|
38
|
+
process_params = Proc.new do |values|
|
39
|
+
# values is a Hash with keys: :content, :instance and value appropriate to key
|
40
|
+
if param_exists.call :failed
|
41
|
+
unless values[:content].nil?
|
42
|
+
params[:failed].add_content values[:content]
|
43
|
+
end
|
44
|
+
unless values[:instance].nil?
|
45
|
+
# appropriate content should be already added
|
46
|
+
params[:failed].add_instance values[:instance]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# result variable
|
52
|
+
is_valid = true
|
53
|
+
# contains contents absent or without valid instances on local system
|
54
|
+
# and corresponding local instances
|
55
|
+
failed = ContentData::ContentData.new
|
56
|
+
# contains checksums of contains absent in local
|
57
|
+
absent_checksums = Array.new
|
58
|
+
|
59
|
+
# contains local instances corresponding to given remote index contents
|
60
|
+
local_index_to_check = ContentData::ContentData.new
|
61
|
+
|
62
|
+
# check whether remote contents exist locally and add them for further validations
|
63
|
+
remote_index.contents.each_key do |checksum|
|
64
|
+
if local_index.content_exists checksum
|
65
|
+
local_index_to_check.add_content local_index.contents[checksum]
|
66
|
+
else
|
67
|
+
is_valid = false
|
68
|
+
failed.add_content remote_index.contents[checksum]
|
69
|
+
absent_checksums << checksum
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# add instances of contents that should be check
|
74
|
+
local_index.instances.each_value do |instance|
|
75
|
+
if remote_index.content_exists instance.checksum
|
76
|
+
local_index_to_check.add_instance instance
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# validate against local file system
|
82
|
+
is_valid = local_index_to_check.validate(:failed => failed) && is_valid
|
83
|
+
|
84
|
+
# contains contents that have at least one valid local instance,
|
85
|
+
# then also corresponding remote content defined valid
|
86
|
+
contents_with_succeeded_instances = ContentData::ContentData.remove_instances failed, local_index
|
87
|
+
|
88
|
+
# write summary to log
|
89
|
+
# TODO should be controlled from params?
|
90
|
+
failed.contents.each_key do |checksum|
|
91
|
+
if absent_checksums.include? checksum
|
92
|
+
Log.warning "Content #{checksum} is absent in the local file system"
|
93
|
+
elsif !contents_with_succeeded_instances.content_exists checksum
|
94
|
+
# if checked content have no valid local instances
|
95
|
+
# then content defined invalid
|
96
|
+
Log.warning "Content #{checksum} is invalid in the local file system"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# if needed process output params
|
101
|
+
unless params.nil? || params.empty?
|
102
|
+
remote_index.instances.each_value do |instance|
|
103
|
+
unless contents_with_succeeded_instances.content_exists instance.checksum
|
104
|
+
process_params.call :content => remote_index.contents[instance.checksum], :instance => instance
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
is_valid
|
110
|
+
end
|
111
|
+
|
112
|
+
end # class IndexValidations
|
113
|
+
end # module Validations
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require_relative '../../lib/validations.rb'
|
3
|
+
|
4
|
+
module Validations
|
5
|
+
module Spec
|
6
|
+
describe 'Index validation' do
|
7
|
+
context 'of index from other file system' do
|
8
|
+
before :all do
|
9
|
+
@size = 100
|
10
|
+
@path = '/dir1/dir2/file'
|
11
|
+
@path2 = '/dir3/dir4/file'
|
12
|
+
@path3 = '/dir5/dir6/file'
|
13
|
+
@path4 = '/dir7/dir8/file'
|
14
|
+
@mod_time = 123456
|
15
|
+
@checksum = 'abcde987654321'
|
16
|
+
@checksum2 = '987654321abcde'
|
17
|
+
end
|
18
|
+
|
19
|
+
before :each do
|
20
|
+
@index = ContentData::ContentData.new
|
21
|
+
@remote_index = ContentData::ContentData.new
|
22
|
+
|
23
|
+
@content = double :content, :checksum => @checksum,
|
24
|
+
:size => @size, :first_appearance_time => @mod_time
|
25
|
+
@content2 = double :content2, :checksum => @checksum2,
|
26
|
+
:size => @size, :first_appearance_time => @mod_time
|
27
|
+
|
28
|
+
@instance = double :instance, :checksum => @checksum, :global_path => @path,
|
29
|
+
:size => @size, :full_path => @path, :modification_time => @mod_time
|
30
|
+
@instance2 = double :instance2, :checksum => @checksum2, :global_path => @path2,
|
31
|
+
:size => @size, :full_path => @path2, :modification_time => @mod_time
|
32
|
+
@instance3 = double :instance3, :checksum => @checksum, :global_path => @path3,
|
33
|
+
:size => @size, :full_path => @path3, :modification_time => @mod_time
|
34
|
+
@instance4 = double :instance4, :checksum => @checksum2, :global_path => @path4,
|
35
|
+
:size => @size, :full_path => @path4, :modification_time => @mod_time
|
36
|
+
|
37
|
+
@index.add_content @content
|
38
|
+
@index.add_content @content2
|
39
|
+
@index.add_instance @instance
|
40
|
+
@index.add_instance @instance2
|
41
|
+
|
42
|
+
@remote_index.add_content @content
|
43
|
+
@remote_index.add_content @content2
|
44
|
+
@remote_index.add_instance @instance3
|
45
|
+
@remote_index.add_instance @instance4
|
46
|
+
|
47
|
+
File.stub(:exists?).and_return(true)
|
48
|
+
File.stub(:size).and_return(@size)
|
49
|
+
File.stub(:mtime).and_return(@mod_time)
|
50
|
+
#ContentData::ContentData.stub(:format_time).with(@mod_time).and_return(@mod_time)
|
51
|
+
Params['instance_check_level'] = 'shallow'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'succeeds when all remote contents has valid local instance' do
|
55
|
+
IndexValidations.validate_remote_index(@remote_index, @index).should be_true
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'fails when remote content is absent' do
|
59
|
+
absent_checksum = '123'
|
60
|
+
absent_content = double :absent_content, :checksum => absent_checksum, \
|
61
|
+
:size => @size, :first_appearance_time => @mod_time
|
62
|
+
@remote_index.add_content absent_content
|
63
|
+
IndexValidations.validate_remote_index(@remote_index, @index).should be_false
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'fails when local instance of remote content is invalid' do
|
67
|
+
modified_mtime = @mod_time + 10
|
68
|
+
File.stub(:mtime).with(@path).and_return(modified_mtime)
|
69
|
+
#ContentData::ContentData.stub(:format_time).with(modified_mtime).and_return(modified_mtime)
|
70
|
+
IndexValidations.validate_remote_index(@remote_index, @index).should be_false
|
71
|
+
end
|
72
|
+
|
73
|
+
it ':failed param returns index of absent contents or contents without valid instances' do
|
74
|
+
absent_checksum = '123'
|
75
|
+
absent_path = '/dir9/dir10/absent_file'
|
76
|
+
absent_content = double :absent_content, :checksum => absent_checksum, \
|
77
|
+
:size => @size, :first_appearance_time => @mod_time
|
78
|
+
absent_instance = double :instance, :checksum => absent_checksum, :global_path => absent_path,
|
79
|
+
:size => @size, :full_path => absent_path, :modification_time => @mod_time
|
80
|
+
@remote_index.add_content absent_content
|
81
|
+
@remote_index.add_instance absent_instance
|
82
|
+
|
83
|
+
# invalid instance has @path2 path on local and @path4 on remote
|
84
|
+
modified_mtime = @mod_time + 10
|
85
|
+
File.stub(:mtime).with(@path2).and_return(modified_mtime)
|
86
|
+
#ContentData::ContentData.stub(:format_time).with(modified_mtime).and_return(modified_mtime)
|
87
|
+
|
88
|
+
failed = ContentData::ContentData.new
|
89
|
+
IndexValidations.validate_remote_index(@remote_index, @index, :failed => failed)
|
90
|
+
failed.contents.should have(2).items
|
91
|
+
failed.contents.keys.should include(absent_checksum, @checksum2)
|
92
|
+
failed.instances.should have(2).items
|
93
|
+
failed.instances.keys.should include(@path4)
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: validations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Genady Petelko
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: log
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: params
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: content_data
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: file_indexing
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: Used to validate ContentData objects.
|
79
|
+
email: nukegluk@gmail.com
|
80
|
+
executables: []
|
81
|
+
extensions: []
|
82
|
+
extra_rdoc_files: []
|
83
|
+
files:
|
84
|
+
- lib/validations.rb
|
85
|
+
- lib/validations/index_validations.rb
|
86
|
+
- lib/validations/version.rb
|
87
|
+
- spec/validations/index_validations_spec.rb
|
88
|
+
homepage: http://github.com/kolmanv/bbfs
|
89
|
+
licenses: []
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
requirements: []
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 1.8.25
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: Library for validating data.
|
112
|
+
test_files:
|
113
|
+
- spec/validations/index_validations_spec.rb
|
114
|
+
has_rdoc:
|