validations 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|