buildpack-support 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data/LICENSE +202 -0
  2. data/NOTICE +2 -0
  3. data/docs/cache.md +77 -0
  4. data/docs/component.md +1 -0
  5. data/docs/configuration.md +27 -0
  6. data/docs/logging.md +54 -0
  7. data/docs/other.md +1 -0
  8. data/docs/rake.md +1 -0
  9. data/docs/repository.md +116 -0
  10. data/docs/test.md +1 -0
  11. data/lib/buildpack_support.rb +18 -0
  12. data/lib/buildpack_support/base_buildpack.rb +166 -0
  13. data/lib/buildpack_support/buildpack_version.rb +124 -0
  14. data/lib/buildpack_support/cache.rb +24 -0
  15. data/lib/buildpack_support/cache/application_cache.rb +41 -0
  16. data/lib/buildpack_support/cache/cached_file.rb +103 -0
  17. data/lib/buildpack_support/cache/download_cache.rb +280 -0
  18. data/lib/buildpack_support/cache/inferred_network_failure.rb +26 -0
  19. data/lib/buildpack_support/cache/internet_availability.rb +64 -0
  20. data/lib/buildpack_support/component.rb +24 -0
  21. data/lib/buildpack_support/component/application.rb +76 -0
  22. data/lib/buildpack_support/component/base_component.rb +78 -0
  23. data/lib/buildpack_support/component/base_droplet.rb +96 -0
  24. data/lib/buildpack_support/component/downloads.rb +88 -0
  25. data/lib/buildpack_support/component/services.rb +84 -0
  26. data/lib/buildpack_support/component/versioned_dependency_component.rb +71 -0
  27. data/lib/buildpack_support/component/versioned_downloads.rb +57 -0
  28. data/lib/buildpack_support/component/with_timing.rb +40 -0
  29. data/lib/buildpack_support/configuration_utils.rb +58 -0
  30. data/lib/buildpack_support/constantize.rb +46 -0
  31. data/lib/buildpack_support/dash_case.rb +29 -0
  32. data/lib/buildpack_support/directory_finder.rb +45 -0
  33. data/lib/buildpack_support/filtering_pathname.rb +227 -0
  34. data/lib/buildpack_support/format_duration.rb +57 -0
  35. data/lib/buildpack_support/logging.rb +22 -0
  36. data/lib/buildpack_support/logging/delegating_logger.rb +48 -0
  37. data/lib/buildpack_support/logging/logger_factory.rb +148 -0
  38. data/lib/buildpack_support/qualify_path.rb +36 -0
  39. data/lib/buildpack_support/rake.rb +22 -0
  40. data/lib/buildpack_support/rake/buildpack_stage_task.rb +86 -0
  41. data/lib/buildpack_support/rake/cached_artifact_finder.rb +99 -0
  42. data/lib/buildpack_support/rake/check_api_doc_task.rb +70 -0
  43. data/lib/buildpack_support/rake/dependency_cache_task.rb +87 -0
  44. data/lib/buildpack_support/rake/disable_remote_downloads_task.rb +80 -0
  45. data/lib/buildpack_support/rake/package_task.rb +133 -0
  46. data/lib/buildpack_support/rake/package_zip_task.rb +80 -0
  47. data/lib/buildpack_support/rake/repository_configuration_finder.rb +66 -0
  48. data/lib/buildpack_support/rake/write_version_file_task.rb +82 -0
  49. data/lib/buildpack_support/repository.rb +24 -0
  50. data/lib/buildpack_support/repository/configured_item.rb +81 -0
  51. data/lib/buildpack_support/repository/repository_index.rb +98 -0
  52. data/lib/buildpack_support/repository/wildcard_version_resolver.rb +75 -0
  53. data/lib/buildpack_support/shell.rb +41 -0
  54. data/lib/buildpack_support/snake_case.rb +30 -0
  55. data/lib/buildpack_support/space_case.rb +29 -0
  56. data/lib/buildpack_support/test/application_helper.rb +41 -0
  57. data/lib/buildpack_support/test/base_component_helper.rb +59 -0
  58. data/lib/buildpack_support/test/base_droplet_helper.rb +36 -0
  59. data/lib/buildpack_support/test/console_helper.rb +57 -0
  60. data/lib/buildpack_support/test/environment_helper.rb +32 -0
  61. data/lib/buildpack_support/test/internet_availability_helper.rb +29 -0
  62. data/lib/buildpack_support/test/logging_helper.rb +50 -0
  63. data/lib/buildpack_support/test/scratch_helper.rb +32 -0
  64. data/lib/buildpack_support/test/versioned_dependency_component_helper.rb +32 -0
  65. data/lib/buildpack_support/test/with_load_path_helper.rb +27 -0
  66. data/lib/buildpack_support/to_b.rb +38 -0
  67. data/lib/buildpack_support/tokenized_version.rb +157 -0
  68. data/lib/buildpack_support/version.rb +23 -0
  69. data/spec/buildpack_support/base_buildpack_spec.rb +112 -0
  70. data/spec/buildpack_support/buildpack_version_spec.rb +122 -0
  71. data/spec/buildpack_support/cache/application_cache_spec.rb +56 -0
  72. data/spec/buildpack_support/cache/cached_file_spec.rb +94 -0
  73. data/spec/buildpack_support/cache/download_cache_spec.rb +293 -0
  74. data/spec/buildpack_support/cache/internet_availability_spec.rb +57 -0
  75. data/spec/buildpack_support/cache/yield_file_with_content.rb +30 -0
  76. data/spec/buildpack_support/component/application_spec.rb +81 -0
  77. data/spec/buildpack_support/component/base_component_spec.rb +81 -0
  78. data/spec/buildpack_support/component/base_droplet_spec.rb +72 -0
  79. data/spec/buildpack_support/component/downloads_spec.rb +63 -0
  80. data/spec/buildpack_support/component/services_spec.rb +80 -0
  81. data/spec/buildpack_support/component/versioned_dependency_component_spec.rb +58 -0
  82. data/spec/buildpack_support/component/versioned_downloads_spec.rb +58 -0
  83. data/spec/buildpack_support/component/with_timing_spec.rb +30 -0
  84. data/spec/buildpack_support/configuration_utils_spec.rb +39 -0
  85. data/spec/buildpack_support/constantize_spec.rb +34 -0
  86. data/spec/buildpack_support/dash_case_spec.rb +41 -0
  87. data/spec/buildpack_support/directory_finder_spec.rb +41 -0
  88. data/spec/buildpack_support/filtering_pathname_spec.rb +443 -0
  89. data/spec/buildpack_support/format_duration_spec.rb +60 -0
  90. data/spec/buildpack_support/logging/delegating_logger_spec.rb +62 -0
  91. data/spec/buildpack_support/logging/logger_factory_spec.rb +262 -0
  92. data/spec/buildpack_support/qualify_path_spec.rb +42 -0
  93. data/spec/buildpack_support/rake/buildpack_stage_task_spec.rb +88 -0
  94. data/spec/buildpack_support/rake/cached_artifact_finder_spec.rb +73 -0
  95. data/spec/buildpack_support/rake/check_api_doc_task_spec.rb +69 -0
  96. data/spec/buildpack_support/rake/dependency_cache_task_spec.rb +133 -0
  97. data/spec/buildpack_support/rake/disable_remote_downloads_task_spec.rb +91 -0
  98. data/spec/buildpack_support/rake/package_task_spec.rb +335 -0
  99. data/spec/buildpack_support/rake/package_zip_task_spec.rb +91 -0
  100. data/spec/buildpack_support/rake/repository_configuration_finder_spec.rb +61 -0
  101. data/spec/buildpack_support/rake/write_version_file_task_spec.rb +96 -0
  102. data/spec/buildpack_support/repository/configured_item_spec.rb +78 -0
  103. data/spec/buildpack_support/repository/repository_index_spec.rb +118 -0
  104. data/spec/buildpack_support/repository/wildcard_version_resolver_spec.rb +73 -0
  105. data/spec/buildpack_support/shell_spec.rb +32 -0
  106. data/spec/buildpack_support/snake_case_spec.rb +45 -0
  107. data/spec/buildpack_support/space_case_spec.rb +41 -0
  108. data/spec/buildpack_support/to_b_spec.rb +41 -0
  109. data/spec/buildpack_support/tokenized_version_spec.rb +132 -0
  110. data/spec/fixtures/application/test-file +0 -0
  111. data/spec/fixtures/config/found-config.yml +2 -0
  112. data/spec/fixtures/droplet-resources/droplet-resource +0 -0
  113. data/spec/fixtures/stub-download-with-top-level.zip +0 -0
  114. data/spec/fixtures/stub-download.tar.gz +0 -0
  115. data/spec/fixtures/stub-download.zip +0 -0
  116. data/spec/fixtures/test-cache.yml +18 -0
  117. data/spec/fixtures/test-index.yml +2 -0
  118. data/spec/fixtures/test_component.rb +0 -0
  119. data/spec/fixtures/zip-contents/test-directory/test-deep-file +0 -0
  120. data/spec/fixtures/zip-contents/test-file +0 -0
  121. data/spec/spec_helper.rb +30 -0
  122. metadata +416 -0
@@ -0,0 +1,58 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2013-2014 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'buildpack_support/component/versioned_downloads'
18
+ require 'buildpack_support/test/base_component_helper'
19
+
20
+ describe BuildpackSupport::Component::VersionedDownloads do
21
+ include_context 'base_component_helper'
22
+
23
+ let(:component) { StubVersionedDownloadsClass.new droplet, uri, version }
24
+
25
+ it 'should download and expand TAR file in the sandbox',
26
+ cache_fixture: 'stub-download.tar.gz' do
27
+
28
+ component.download_tar
29
+ expect(droplet.sandbox + 'test-file').to exist
30
+ end
31
+
32
+ it 'should download and expand ZIP file in the sandbox',
33
+ cache_fixture: 'stub-download.zip' do
34
+
35
+ component.download_zip(false)
36
+ expect(droplet.sandbox + 'test-file').to exist
37
+ end
38
+
39
+ it 'should download and expand ZIP file, stripping the top level directory in the sandbox',
40
+ cache_fixture: 'stub-download-with-top-level.zip' do
41
+
42
+ component.download_zip
43
+ expect(droplet.sandbox + 'test-file').to exist
44
+ end
45
+
46
+ end
47
+
48
+ class StubVersionedDownloadsClass
49
+ include BuildpackSupport::Component::VersionedDownloads
50
+
51
+ def initialize(droplet, uri, version)
52
+ @component_name = 'Stub Component'
53
+ @droplet = droplet
54
+ @uri = uri
55
+ @version = version
56
+ end
57
+
58
+ end
@@ -0,0 +1,30 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2013-2014 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'buildpack_support/component/with_timing'
18
+ require 'buildpack_support/test/console_helper'
19
+
20
+ describe BuildpackSupport::Component::WithTiming do
21
+ include BuildpackSupport::Component::WithTiming
22
+ include_context 'console_helper'
23
+
24
+ it 'should print timing information' do
25
+ expect { |b| with_timing('test-caption', &b) }.to yield_control
26
+
27
+ expect(stdout.string).to match(/ test-caption \([\d]\.[\d]s\)/)
28
+ end
29
+
30
+ end
@@ -0,0 +1,39 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2013-2014 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'buildpack_support/configuration_utils'
18
+ require 'buildpack_support/test/logging_helper'
19
+ require 'buildpack_support/test/with_load_path_helper'
20
+
21
+ describe BuildpackSupport::ConfigurationUtils do
22
+ include_context 'with_load_path_helper'
23
+ include_context 'logging_helper'
24
+
25
+ let(:configurationUtils) { described_class.new }
26
+
27
+ it 'should return the empty configuration for a non-existent configuration file' do
28
+ with_load_path('spec/fixtures/load-path') do
29
+ expect(configurationUtils.load('not-found-config')).to eq({})
30
+ end
31
+ end
32
+
33
+ it 'should return the configuration for a configuration file' do
34
+ with_load_path('spec/fixtures/load-path') do
35
+ expect(configurationUtils.load('found-config')).to eq('foo' => 'bar')
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,34 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2013-2014 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'buildpack_support/constantize'
18
+
19
+ describe 'constantize' do
20
+
21
+ it 'should constantize string' do
22
+ expect('Test::StubClass'.constantize).to eq(Test::StubClass)
23
+ end
24
+
25
+ it 'should raise error if constant does not exist' do
26
+ expect { 'Test::StubClass2'.constantize }.to raise_error(NameError)
27
+ end
28
+
29
+ end
30
+
31
+ module Test
32
+ class StubClass
33
+ end
34
+ end
@@ -0,0 +1,41 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2013-2014 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'buildpack_support/dash_case'
18
+
19
+ describe 'dash_case' do
20
+
21
+ it 'should return only lowercase strings' do
22
+ expect('Test'.dash_case).to eq('test')
23
+ end
24
+
25
+ it 'should return the last module name' do
26
+ expect('Foo::Bar::Bang'.dash_case).to eq('bang')
27
+ end
28
+
29
+ it 'should split on penultimate uppercase characters' do
30
+ expect('FOOBar'.dash_case).to eq('foo-bar')
31
+ end
32
+
33
+ it 'should split on lowercase characters followed an uppercase characters' do
34
+ expect('FooBar'.dash_case).to eq('foo-bar')
35
+ end
36
+
37
+ it 'should split on digit characters followed an uppercase characters' do
38
+ expect('123Bar'.dash_case).to eq('123-bar')
39
+ end
40
+
41
+ end
@@ -0,0 +1,41 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2013-2014 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'buildpack_support/directory_finder'
18
+ require 'buildpack_support/test/with_load_path_helper'
19
+
20
+ describe BuildpackSupport::DirectoryFinder do
21
+ include_context 'with_load_path_helper'
22
+
23
+ let(:directoryFinder) { StubDirectoryFinderClass.new }
24
+
25
+ it 'should find the path' do
26
+ with_load_path('spec/fixtures/load-path') do
27
+ expect(directoryFinder.load_path_peer('found-directory')).to exist
28
+ end
29
+ end
30
+
31
+ it 'should not find the not found directory' do
32
+ with_load_path('spec/fixtures/load-path') do
33
+ expect(directoryFinder.load_path_peer('not-found-directory')).not_to exist
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ class StubDirectoryFinderClass
40
+ include BuildpackSupport::DirectoryFinder
41
+ end
@@ -0,0 +1,443 @@
1
+ # Encoding: utf-8
2
+ # Copyright 2013-2014 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'buildpack_support/filtering_pathname'
18
+ require 'buildpack_support/test/scratch_helper'
19
+ require 'fileutils'
20
+ require 'set'
21
+
22
+ describe BuildpackSupport::FilteringPathname do
23
+ include_context 'scratch_helper'
24
+
25
+ let(:filter_none) { ->(_) { true } }
26
+ let(:filter_all) { ->(_) { false } }
27
+ let(:filter_goodness) { ->(pathname) { pathname.basename != Pathname.new('bad') } }
28
+ let(:filter_strict) { ->(pathname) { pathname.basename == Pathname.new('good') } }
29
+ let(:filtering_target) { described_class.new(scratch_dir, filter_goodness, false) }
30
+ let(:strict_filtering_target) { described_class.new(scratch_dir, filter_strict, false) }
31
+ let(:filtered_target) { described_class.new(scratch_dir, filter_all, false) }
32
+ let(:immutable_target) { described_class.new(scratch_dir, filter_goodness, false) }
33
+ let(:mutable_target) { described_class.new(scratch_dir, filter_goodness, true) }
34
+ let(:filename_target) { described_class.new(Pathname.new('/a/b'), filter_goodness, true) }
35
+
36
+ before do
37
+ create_file 'good'
38
+ create_file 'bad'
39
+ end
40
+
41
+ it 'delegate to pathnames which exist and are not filtered' do
42
+ filtering_pathname = described_class.new(scratch_dir, filter_none, false)
43
+ expect(filtering_pathname.ftype).to eq('directory')
44
+ end
45
+
46
+ it 'delegate to pathnames which do not exist' do
47
+ filtering_pathname = described_class.new(scratch_dir + 'no-such-file', filter_none, false)
48
+ expect { filtering_pathname.ftype }.to raise_error(/No such file or directory/)
49
+ end
50
+
51
+ it 'delegate to pathnames which exist but which are filtered' do
52
+ filtering_pathname = described_class.new(scratch_dir, filter_all, false)
53
+ expect { filtering_pathname.ftype }.to raise_error(/No such file or directory/)
54
+ end
55
+
56
+ it 'should fail to construct if a .nil file exists' do
57
+ FileUtils.touch Pathname.new("#{scratch_dir}.nil")
58
+ expect { described_class.new(scratch_dir, filter_all, false) }.to raise_error(/should not exist/)
59
+ end
60
+
61
+ it 'should fail if a .nil file is created after construction' do
62
+ filtering_pathname = described_class.new(scratch_dir + 'test.file', filter_all, false)
63
+ FileUtils.touch(scratch_dir + 'test.file.nil')
64
+
65
+ expect { filtering_pathname.ftype }.to raise_error(/should not exist/)
66
+ end
67
+
68
+ it 'should fail to construct if a .nil directory exists' do
69
+ FileUtils.mkdir_p Pathname.new("#{scratch_dir}.nil")
70
+ expect { described_class.new(scratch_dir, filter_all, false) }.to raise_error(/should not exist/)
71
+ end
72
+
73
+ it 'should return a missing method' do
74
+ expect { described_class.new(scratch_dir, filter_all, false).method(:chardev?) }.not_to raise_error
75
+ end
76
+
77
+ it 'should filter the result of +' do
78
+ expect(filtering_target + 'good').to exist
79
+ expect(filtering_target + 'bad').not_to exist
80
+ end
81
+
82
+ it 'should correctly stringify non-clean paths' do
83
+ expect(described_class.new(Pathname.new('/a/b/..'), filter_none, false).to_s).to eq('/a/b/..')
84
+ end
85
+
86
+ it 'should produce correct result for + with a non-clean path' do
87
+ base = described_class.new(Pathname.new('/a'), filter_none, false)
88
+ expect((base + 'b/..').to_s).to eq('/a/b/..')
89
+ end
90
+
91
+ it 'should produce correct result for + with a non-clean path starting with '..'' do
92
+ base = described_class.new(Pathname.new('/a/b'), filter_none, false)
93
+ expect((base + '..').to_s).to eq('/a')
94
+ end
95
+
96
+ it 'should filter the result of join' do
97
+ expect(filtering_target.join 'good').to exist
98
+ expect(filtering_target.join 'bad').not_to exist
99
+ end
100
+
101
+ it 'should filter the result of parent', :filter do
102
+ expect((filtering_target + 'good' + 'extra').parent).to exist
103
+ expect((filtering_target + 'bad' + 'extra').parent).not_to exist
104
+ end
105
+
106
+ it 'should compare to pathnames correctly using <=>' do
107
+ expect((filtering_target + 'good') <=> (scratch_dir + 'good')).to eq(0)
108
+ expect((filtering_target + 'good') <=> (scratch_dir + 'bad')).to eq(1)
109
+ expect((filtering_target + 'bad') <=> (scratch_dir + 'bad')).to eq(0)
110
+ expect((filtering_target + 'a') <=> (scratch_dir + 'b')).to eq(-1)
111
+ expect((filtering_target + 'b') <=> (scratch_dir + 'a')).to eq(1)
112
+ end
113
+
114
+ it 'should compare to filtering pathnames correctly using <=>' do
115
+ expect((filtering_target + 'good') <=> (filtering_target + 'good')).to eq(0) # rubocop:disable UselessComparison
116
+ expect((filtering_target + 'good') <=> (filtering_target + 'bad')).to eq(1)
117
+ expect((filtering_target + 'bad') <=> (filtering_target + 'bad')).to eq(0) # rubocop:disable UselessComparison
118
+ expect((filtering_target + 'a') <=> (filtering_target + 'b')).to eq(-1)
119
+ expect((filtering_target + 'b') <=> (filtering_target + 'a')).to eq(1)
120
+ end
121
+
122
+ it 'should support sorting' do
123
+ a = (filtering_target + 'a')
124
+ b = (filtering_target + 'b')
125
+ expect([b, a].sort).to eq([a, b])
126
+ end
127
+
128
+ it 'should compare to pathnames correctly using ==' do
129
+ expect((filtering_target + 'good') == (scratch_dir + 'good')).to be
130
+ expect((filtering_target + 'bad') == (scratch_dir + 'bad')).to be
131
+ end
132
+
133
+ it 'should compare to filtering pathnames correctly using ==' do
134
+ expect((filtering_target + 'good') == (filtering_target + 'good')).to be # rubocop:disable UselessComparison
135
+ expect((filtering_target + 'bad') == (filtering_target + 'bad')).to be # rubocop:disable UselessComparison
136
+ end
137
+
138
+ it 'should compare to pathnames correctly using ===' do
139
+ expect((filtering_target + 'good') === (scratch_dir + 'good')).to be # rubocop:disable CaseEquality
140
+ expect((filtering_target + 'bad') === (scratch_dir + 'bad')).to be # rubocop:disable CaseEquality
141
+ end
142
+
143
+ it 'should compare to filtering pathnames correctly using ===' do
144
+ expect((filtering_target + 'good') === (filtering_target + 'good')).to be # rubocop:disable CaseEquality, UselessComparison
145
+ expect((filtering_target + 'bad') === (filtering_target + 'bad')).to be # rubocop:disable CaseEquality, UselessComparison
146
+ end
147
+
148
+ it 'should delegate relative_path_from' do
149
+ target = filtering_target + 'test1'
150
+ underlying_pathname = target.send :pathname
151
+ expect(underlying_pathname).to receive(:relative_path_from) { Pathname.new('test1') }
152
+ relative_path = target.relative_path_from(Pathname.new(scratch_dir))
153
+ expect(relative_path).to eq(Pathname.new('test1'))
154
+ end
155
+
156
+ it 'should return path when to_s is called when the path is not filtered out' do
157
+ expect(filtering_target.to_s).to eq(scratch_dir.to_s)
158
+ end
159
+
160
+ it 'should return path when to_s is called when the path is filtered out' do
161
+ expect(filtered_target.to_s).to eq(scratch_dir.to_s)
162
+ end
163
+
164
+ it 'should yield a Pathname for each visible result from each_entry' do
165
+ entries = []
166
+ filtering_target.each_entry do |entry|
167
+ entries << entry
168
+ end
169
+ expect(entries.to_set).to eq([Pathname.new('.'), Pathname.new('..'), Pathname.new('good')].to_set)
170
+ end
171
+
172
+ it 'should delegate each_line when the file is filtered in' do
173
+ target = filtering_target + 'good'
174
+ underlying_pathname = target.send :pathname
175
+ expect(underlying_pathname).to receive(:each_line).and_yield('test-line')
176
+ expect { |b| target.each_line(&b) }.to yield_successive_args('test-line')
177
+ end
178
+
179
+ it 'should raise error from each_line when the file is filtered out' do
180
+ expect { (filtering_target + 'bad').each_line { |_| } }.to raise_exception Errno::ENOENT
181
+ end
182
+
183
+ it 'should return each visible entry from entries' do
184
+ expect(filtering_target.entries.to_set).to eq([Pathname.new('.'), Pathname.new('..'), Pathname.new('good')].to_set)
185
+ end
186
+
187
+ it 'should delegate opendir when the directory is filtered in' do
188
+ expect(scratch_dir).to receive(:opendir).and_yield('test-dir')
189
+ expect { |b| filtering_target.opendir(&b) }.to yield_successive_args('test-dir')
190
+ end
191
+
192
+ it 'should raise error from opendir when the file is filtered out' do
193
+ expect { (filtering_target + 'bad').opendir { |_| } }.to raise_exception Errno::ENOENT
194
+ end
195
+
196
+ it 'should delegate sysopen when the file is filtered in' do
197
+ target = filtering_target + 'good'
198
+ underlying_pathname = target.send :pathname
199
+ expect(underlying_pathname).to receive(:sysopen).and_yield(999)
200
+ expect { |b| target.sysopen(&b) }.to yield_successive_args(999)
201
+ end
202
+
203
+ it 'should raise error from sysopen when the file is filtered out' do
204
+ expect { (filtering_target + 'bad').sysopen { |_| } }.to raise_exception Errno::ENOENT
205
+ end
206
+
207
+ it 'should return each child as a filtered pathname from children' do
208
+ expect(filtering_target.children).to eq([scratch_dir + 'good'])
209
+ end
210
+
211
+ it 'should return each child as a pathname from children(false)' do
212
+ expect(filtering_target.children(false)).to eq([Pathname.new('good')])
213
+ end
214
+
215
+ it 'should yield each child as a filtered pathname from each_child' do
216
+ expect { |b| filtering_target.each_child(&b) }.to yield_successive_args(scratch_dir + 'good')
217
+ end
218
+
219
+ it 'should yield each child as a pathname from each_child(false)' do
220
+ expect { |b| filtering_target.each_child(false, &b) }.to yield_successive_args(Pathname.new('good'))
221
+ end
222
+
223
+ it 'should yield each component of the path from each_filename' do
224
+ expect { |b| filename_target.each_filename(&b) }.to yield_successive_args('a', 'b')
225
+ end
226
+
227
+ it 'should yield each element of the path from descend' do
228
+ expect { |b| filename_target.descend(&b) }.to yield_successive_args(Pathname.new('/'), Pathname.new('/a'),
229
+ Pathname.new('/a/b'))
230
+ end
231
+
232
+ it 'should yield each element of the path from ascend' do
233
+ expect { |b| filename_target.ascend(&b) }.to yield_successive_args(Pathname.new('/a/b'), Pathname.new('/a'),
234
+ Pathname.new('/'))
235
+ end
236
+
237
+ it 'should raise error if chmod is called on an immutable instance' do
238
+ expect { immutable_target.chmod(0644) }.to raise_error(/FilteringPathname is immutable/)
239
+ end
240
+
241
+ it 'should delegate if chmod is called on a mutable instance' do
242
+ expect(scratch_dir).to receive(:chmod)
243
+ mutable_target.chmod(0644)
244
+ end
245
+
246
+ it 'should raise error if chown is called on an immutable instance' do
247
+ expect { immutable_target.chown('test-user', 100) }.to raise_error(/FilteringPathname is immutable/)
248
+ end
249
+
250
+ it 'should delegate if chown is called on a mutable instance' do
251
+ expect(scratch_dir).to receive(:chown)
252
+ mutable_target.chown('test-user', 100)
253
+ end
254
+
255
+ it 'should raise error if delete is called on an immutable instance' do
256
+ expect { immutable_target.delete }.to raise_error(/FilteringPathname is immutable/)
257
+ end
258
+
259
+ it 'should delegate if delete is called on a mutable instance' do
260
+ expect(scratch_dir).to receive(:delete)
261
+ mutable_target.delete
262
+ end
263
+
264
+ it 'should raise error if lchmod is called on an immutable instance' do
265
+ expect { immutable_target.lchmod(0644) }.to raise_error(/FilteringPathname is immutable/)
266
+ end
267
+
268
+ it 'should delegate if lchmod is called on a mutable instance' do
269
+ expect(scratch_dir).to receive(:lchmod)
270
+ mutable_target.lchmod(0644)
271
+ end
272
+
273
+ it 'should raise error if lchown is called on an immutable instance' do
274
+ expect { immutable_target.lchown('test-user', 100) }.to raise_error(/FilteringPathname is immutable/)
275
+ end
276
+
277
+ it 'should delegate if lchown is called on a mutable instance' do
278
+ expect(scratch_dir).to receive(:lchown)
279
+ mutable_target.lchown('test-user', 100)
280
+ end
281
+
282
+ it 'should raise error if make_link is called on an immutable instance' do
283
+ expect { immutable_target.make_link('test') }.to raise_error(/FilteringPathname is immutable/)
284
+ end
285
+
286
+ it 'should delegate if make_link is called on a mutable instance' do
287
+ expect(scratch_dir).to receive(:make_link)
288
+ mutable_target.make_link('test')
289
+ end
290
+
291
+ it 'should raise error if make_symlink is called on an immutable instance' do
292
+ expect { immutable_target.make_symlink('test') }.to raise_error(/FilteringPathname is immutable/)
293
+ end
294
+
295
+ it 'should delegate if make_symlink is called on a mutable instance' do
296
+ expect(scratch_dir).to receive(:make_symlink)
297
+ mutable_target.make_symlink('test')
298
+ end
299
+
300
+ it 'should raise error if mkdir is called on an immutable instance' do
301
+ expect { immutable_target.mkdir('test') }.to raise_error(/FilteringPathname is immutable/)
302
+ end
303
+
304
+ it 'should delegate if mkdir is called on a mutable instance' do
305
+ expect(scratch_dir).to receive(:mkdir)
306
+ mutable_target.mkdir('test')
307
+ end
308
+
309
+ it 'should raise error if open is called on an immutable instance with a mutating mode' do
310
+ expect { immutable_target.open('w') { |_| } }.to raise_error(/FilteringPathname is immutable/)
311
+ expect { immutable_target.open('w+') { |_| } }.to raise_error(/FilteringPathname is immutable/)
312
+ expect { immutable_target.open('a') { |_| } }.to raise_error(/FilteringPathname is immutable/)
313
+ expect { immutable_target.open('a+') { |_| } }.to raise_error(/FilteringPathname is immutable/)
314
+ end
315
+
316
+ it 'should delegate if open is called on an immutable instance with a non-mutating mode' do
317
+ expect(scratch_dir).to receive(:open)
318
+ immutable_target.open('r') { |_| }
319
+ end
320
+
321
+ it 'should delegate if open is called on a mutable instance' do
322
+ expect(scratch_dir).to receive(:open)
323
+ mutable_target.open('w') { |_| }
324
+ end
325
+
326
+ it 'should delegate correctly if open is called on a mutable instance with permissions' do
327
+ expect(scratch_dir).to receive(:open).with('w', 0755)
328
+ mutable_target.open('w', 0755) { |_| }
329
+ end
330
+
331
+ it 'should delegate correctly if open is called on a mutable instance with permissions and options' do
332
+ expect(scratch_dir).to receive(:open).with('w', 0755, external_encoding: 'UTF-8')
333
+ mutable_target.open('w', 0755, external_encoding: 'UTF-8') { |_| }
334
+ end
335
+
336
+ it 'should delegate correctly if open is called on a mutable instance with options but no permissions' do
337
+ expect(scratch_dir).to receive(:open).with('w', external_encoding: 'UTF-8')
338
+ mutable_target.open('w', external_encoding: 'UTF-8') { |_| }
339
+ end
340
+
341
+ it 'should cope with options on open' do
342
+ content = (immutable_target + 'good').open('r', external_encoding: 'UTF-8') do |file|
343
+ file.read
344
+ end
345
+ expect(content).to eq('good')
346
+ end
347
+
348
+ it 'should raise error if rename is called on an immutable instance' do
349
+ expect { immutable_target.rename('test') }.to raise_error(/FilteringPathname is immutable/)
350
+ end
351
+
352
+ it 'should delegate if rename is called on a mutable instance' do
353
+ expect(scratch_dir).to receive(:rename)
354
+ mutable_target.rename('test')
355
+ end
356
+
357
+ it 'should raise error if rmdir is called on an immutable instance' do
358
+ expect { immutable_target.rmdir }.to raise_error(/FilteringPathname is immutable/)
359
+ end
360
+
361
+ it 'should delegate if rmdir is called on a mutable instance' do
362
+ expect(scratch_dir).to receive(:rmdir)
363
+ mutable_target.rmdir
364
+ end
365
+
366
+ it 'should raise error if unlink is called on an immutable instance' do
367
+ expect { immutable_target.unlink }.to raise_error(/FilteringPathname is immutable/)
368
+ end
369
+
370
+ it 'should delegate if unlink is called on a mutable instance' do
371
+ expect(scratch_dir).to receive(:unlink)
372
+ mutable_target.unlink
373
+ end
374
+
375
+ it 'should raise error if untaint is called on an immutable instance' do
376
+ expect { immutable_target.untaint }.to raise_error(/FilteringPathname is immutable/)
377
+ end
378
+
379
+ it 'should delegate if untaint is called on a mutable instance' do
380
+ expect(scratch_dir).to receive(:untaint)
381
+ mutable_target.untaint
382
+ end
383
+
384
+ it 'should raise error if taint is called on an immutable instance' do
385
+ expect { immutable_target.taint }.to raise_error(/FilteringPathname is immutable/)
386
+ end
387
+
388
+ it 'should delegate if taint is called on a mutable instance' do
389
+ expect(scratch_dir).to receive(:taint)
390
+ mutable_target.taint
391
+ end
392
+
393
+ it 'should raise error if mkpath is called on an immutable instance' do
394
+ expect { immutable_target.mkpath }.to raise_error(/FilteringPathname is immutable/)
395
+ end
396
+
397
+ it 'should delegate if mkpath is called on a mutable instance' do
398
+ expect(scratch_dir).to receive(:mkpath)
399
+ mutable_target.mkpath
400
+ end
401
+
402
+ it 'should raise error if rmtree is called on an immutable instance' do
403
+ expect { immutable_target.rmtree }.to raise_error(/FilteringPathname is immutable/)
404
+ end
405
+
406
+ it 'should delegate if rmtree is called on a mutable instance' do
407
+ expect(scratch_dir).to receive(:rmtree)
408
+ mutable_target.rmtree
409
+ end
410
+
411
+ it 'should glob and filter the result' do
412
+ g = strict_filtering_target + '*'
413
+ expect(g.glob).to eq([scratch_dir + 'good'])
414
+ end
415
+
416
+ it 'should glob and yield the result' do
417
+ g = strict_filtering_target + '*'
418
+ expect { |b| g.glob(&b) }.to yield_successive_args(scratch_dir + 'good')
419
+ end
420
+
421
+ it 'should raise error if getwd is used' do
422
+ expect { described_class.getwd }.to raise_error(/undefined method `getwd'/)
423
+ end
424
+
425
+ it 'should raise error if glob is used' do
426
+ expect { described_class.glob '' }.to raise_error(/undefined method `glob'/)
427
+ end
428
+
429
+ it 'should raise error if pwd is used' do
430
+ expect { described_class.pwd }.to raise_error(/undefined method `pwd'/)
431
+ end
432
+
433
+ def create_file(filename)
434
+ file = scratch_dir + filename
435
+ FileUtils.mkdir_p file.dirname
436
+ file.open('w') do |f|
437
+ f.write filename
438
+ end
439
+
440
+ file
441
+ end
442
+
443
+ end