redhead 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +445 -0
- data/lib/redhead.rb +37 -0
- data/lib/redhead/header.rb +83 -0
- data/lib/redhead/header_set.rb +134 -0
- data/lib/redhead/redhead_string.rb +62 -0
- data/rakefile +11 -0
- data/test/header_set_spec.rb +344 -0
- data/test/header_spec.rb +270 -0
- data/test/redhead_spec.rb +1 -0
- data/test/redhead_string_spec.rb +114 -0
- data/test/test_helper.rb +1 -0
- metadata +87 -0
data/test/header_spec.rb
ADDED
@@ -0,0 +1,270 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Redhead::Header do
|
4
|
+
before(:each) do
|
5
|
+
@header_name = :a_header_name
|
6
|
+
@header_raw_name = "A-Header-Name"
|
7
|
+
@header_value = "some value"
|
8
|
+
@separator = Redhead::HEADER_NAME_VALUE_SEPARATOR_CHARACTER
|
9
|
+
|
10
|
+
@full_header_string = "#{@header_raw_name}#{@separator} #{@header_value}"
|
11
|
+
|
12
|
+
@header = Redhead::Header.new(:a_header_name, "A-Header-Name", "some value")
|
13
|
+
@header_copy = Redhead::Header.new(:a_header_name, "A-Header-Name", "some value")
|
14
|
+
|
15
|
+
@different_header_raw_name = "An original HEADER name"
|
16
|
+
@header_different_name = Redhead::Header.new(:a_header_name, "An original HEADER name", "something here")
|
17
|
+
|
18
|
+
@default_to_raw = Redhead.to_raw
|
19
|
+
@default_to_key = Redhead.to_key
|
20
|
+
end
|
21
|
+
|
22
|
+
context "as a class" do
|
23
|
+
it "responds to :parse" do
|
24
|
+
Redhead::Header.respond_to?(:parse).should be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "self.parse" do
|
28
|
+
it "parses a string and returns a header" do
|
29
|
+
parsed_header = Redhead::Header.parse(@full_header_string)
|
30
|
+
parsed_header.class.should == Redhead::Header
|
31
|
+
parsed_header.should_not be_nil
|
32
|
+
parsed_header.key.should == @header_name
|
33
|
+
parsed_header.value.should == @header_value
|
34
|
+
parsed_header.raw.should == @header_raw_name
|
35
|
+
end
|
36
|
+
|
37
|
+
it "ignores consecutive non-separating characters by default" do
|
38
|
+
parsed_header = Redhead::Header.parse("one very strange!!! header: anything")
|
39
|
+
parsed_header.key.should == :one_very_strange_header
|
40
|
+
end
|
41
|
+
|
42
|
+
it "ignores whitespace around `:` by default" do
|
43
|
+
spaces = []
|
44
|
+
|
45
|
+
20.times do |n|
|
46
|
+
spaces << [" "*rand(n), " "*rand(n)]
|
47
|
+
end
|
48
|
+
|
49
|
+
spaces.each do |before, after|
|
50
|
+
Redhead::Header.parse("#{@header_raw_name}#{before}:#{after}#{@header_value}").key.should == @header_name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "with a given block" do
|
55
|
+
it "uses the given block as to_key" do
|
56
|
+
Redhead::Header.parse(@full_header_string) { :foo }.key.should == :foo
|
57
|
+
end
|
58
|
+
|
59
|
+
# do not set to_key to the given block so that using parse with a block does not prevent any dynamic
|
60
|
+
# calls up the chain to work out what to_raw should be for each object. i.e., Header#to_key should default
|
61
|
+
# to Redhead.to_key, but since each header doesn't know which headerset it's in, HeaderSet needs to pass down
|
62
|
+
# a block to each Header object. if the Header object set the block as to_key, there'd be problems.
|
63
|
+
#
|
64
|
+
# Similarly, Redhead::String.parse(..., &blk) should not set Header#to_key because then there'd never be any
|
65
|
+
# calls up the hierarchy, since an individual Header's @to_key would exist already.
|
66
|
+
it "sets to_key to the given block" do
|
67
|
+
# note: Proc#== bug!
|
68
|
+
to_key = proc { :foo }
|
69
|
+
Redhead::Header.parse(@full_header_string, &to_key).to_key.should_not == to_key
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#key" do
|
76
|
+
it "returns the symbolic header name" do
|
77
|
+
@header.key.should == :a_header_name
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#key!" do
|
82
|
+
it "uses #to_key to convert #raw to a header key" do
|
83
|
+
@header.to_key = proc { "test" }
|
84
|
+
@header.key!.should == "test"
|
85
|
+
|
86
|
+
@header.to_key = proc { |x| x.upcase.reverse.gsub("-", "_").to_sym }
|
87
|
+
@header.key!.should == @header_raw_name.upcase.reverse.gsub("-", "_").to_sym
|
88
|
+
end
|
89
|
+
|
90
|
+
it "does not change #key after being called" do
|
91
|
+
@header.to_key = proc { "test" }
|
92
|
+
@header.key.should == @header_name
|
93
|
+
@header.key!.should == "test"
|
94
|
+
@header.key.should_not == "test"
|
95
|
+
@header.key.should == @header_name
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "#raw" do
|
100
|
+
it "returns the raw header name stored at creation time" do
|
101
|
+
@header.raw.should == @header_raw_name
|
102
|
+
@header.to_raw = proc { "" }
|
103
|
+
@header.raw!.should == ""
|
104
|
+
@header.raw.should == @header_raw_name
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#raw!" do
|
109
|
+
it "uses #to_raw to convert #key to a raw header, ignoring the value of #raw" do
|
110
|
+
@header.to_raw = proc { "test" }
|
111
|
+
@header.raw!.should == "test"
|
112
|
+
|
113
|
+
@header.to_raw = proc { |x| x.to_s.upcase.reverse }
|
114
|
+
@header.raw!.should == @header_name.to_s.upcase.reverse
|
115
|
+
end
|
116
|
+
|
117
|
+
it "does not change #raw after being called" do
|
118
|
+
@header.to_raw = proc { "test" }
|
119
|
+
@header.raw.should == @header_raw_name
|
120
|
+
@header.raw!.should == "test"
|
121
|
+
@header.raw.should_not == "test"
|
122
|
+
@header.raw.should == @header_raw_name
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "#value" do
|
127
|
+
it "returns the header value" do
|
128
|
+
@header.value.should == @header_value
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#value=" do
|
133
|
+
it "sets a new header value" do
|
134
|
+
@header.value = "new value"
|
135
|
+
@header.value.should == "new value"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#to_s" do
|
140
|
+
it "returns <raw><separator> <value>" do
|
141
|
+
@header.to_s.should == @full_header_string
|
142
|
+
end
|
143
|
+
|
144
|
+
context "with a block" do
|
145
|
+
it "uses the given block to convert #key to a raw header, and returns the raw string" do
|
146
|
+
@header.to_s { "test" }.should == "test#{@separator} #{@header_value}"
|
147
|
+
end
|
148
|
+
|
149
|
+
it "does not set a new value for #to_raw" do
|
150
|
+
@header.to_s { "test" }
|
151
|
+
@header.to_s.should_not == "test#{@separator} #{@header_value}"
|
152
|
+
@header.to_s.should == @full_header_string
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it "takes an optional argument which specifies the raw header to use, without side-effects" do
|
157
|
+
@header.to_s("test").should_not == @full_header_string
|
158
|
+
@header.to_s("test").should == "test#{@separator} #{@header_value}"
|
159
|
+
@header.to_s.should == @full_header_string
|
160
|
+
@header.to_s.should_not == "test#{@separator} #{@header_value}"
|
161
|
+
end
|
162
|
+
|
163
|
+
it "ignores the given block if there is an explicit raw header name" do
|
164
|
+
@header.to_s("test") { "foo" }.should_not == "foo#{@separator} #{@header_value}"
|
165
|
+
@header.to_s("test") { "foo" }.should == "test#{@separator} #{@header_value}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#==(other)" do
|
170
|
+
it "returns true if self.raw == other.raw && self.value == other.value, otherwise false" do
|
171
|
+
@header_copy.value = "something else entirely"
|
172
|
+
@header.should_not == @header_copy
|
173
|
+
|
174
|
+
# same raw name, same value
|
175
|
+
Redhead::Header.new(:a_header_name, "A-Header-Name", "a").should == Redhead::Header.new(:a_header_name, "A-Header-Name", "a")
|
176
|
+
|
177
|
+
# same raw name, different value
|
178
|
+
Redhead::Header.new(:a_header_name, "A-Header-Name", "a").should_not == Redhead::Header.new(:a_header_name, "A-Header-Name", "aaaaaaa")
|
179
|
+
|
180
|
+
# different raw name, same value
|
181
|
+
Redhead::Header.new(:a_header_name, "A-Header-Name", "a").should_not == Redhead::Header.new(:a_header_name, "A-Header-Nameeeeeeee", "a")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "#reversible?" do
|
186
|
+
it "returns true for the defaults" do
|
187
|
+
@header.reversible?.should be_true
|
188
|
+
end
|
189
|
+
|
190
|
+
it "returns true if self.to_raw[self.key!] == self.raw, i.e., if we can't recover the current raw header name via to_key(to_raw(current_raw_header_name))" do
|
191
|
+
@header.to_raw[@header.key!].should == @header_raw_name
|
192
|
+
@header.reversible?.should be_true # by default
|
193
|
+
|
194
|
+
@header.to_raw = proc { |x| "1#{x}" }
|
195
|
+
@header.to_key = proc { |x| "2#{x}" }
|
196
|
+
@header.to_raw[@header.key!].should_not == @header_raw_name
|
197
|
+
@header.reversible?.should be_false # :key does not equal 2Key1Key
|
198
|
+
|
199
|
+
@header.to_raw = proc { |x| x.to_s.reverse }
|
200
|
+
@header.to_key = proc { |x| x.reverse.to_sym }
|
201
|
+
@header.to_raw[@header.key!].should == @header_raw_name
|
202
|
+
@header.reversible?.should be_true
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "#to_raw" do
|
207
|
+
it "returns Redhead.to_raw by default" do
|
208
|
+
# note: Proc#== bug!
|
209
|
+
@header.to_raw.should == @default_to_raw
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "#to_key" do
|
214
|
+
it "returns Redhead.to_key by default" do
|
215
|
+
# note: Proc#== bug!
|
216
|
+
@header.to_key.should == @default_to_key
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "#to_raw=(blk)" do
|
221
|
+
it "sets to_raw to blk" do
|
222
|
+
new_block = proc { }
|
223
|
+
@header.to_raw.should_not == new_block
|
224
|
+
@header.to_raw = new_block
|
225
|
+
@header.to_raw.should == new_block
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "#to_key=(blk)" do
|
230
|
+
it "sets to_key to blk" do
|
231
|
+
new_block = proc { "" + "" }
|
232
|
+
@header.to_key.should_not == new_block
|
233
|
+
@header.to_key = new_block
|
234
|
+
@header.to_key.should == new_block
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "#to_s!" do
|
239
|
+
# TODO: this test doesn't do what it should. know what @header.raw! is going to be and use it in this test
|
240
|
+
# instead of relying on @header.raw! in this test itself. better go through all tests and double-check this.
|
241
|
+
it "returns <raw!><separator> <value>" do
|
242
|
+
@header.to_s!.should == "#{@header.raw!}#{@separator} #{@header_value}"
|
243
|
+
end
|
244
|
+
|
245
|
+
context "with a block argument" do
|
246
|
+
it "uses the given block as though it were #to_raw" do
|
247
|
+
@header.to_s! { "testing" }.should == "testing: #{@header_value}"
|
248
|
+
@header.to_s! { |x| x.to_s.upcase.reverse.gsub("_", "-") }.should == "#{@header_raw_name.to_s.upcase.reverse}: #{@header_value}"
|
249
|
+
end
|
250
|
+
|
251
|
+
it "does not leave to_raw as the given block" do
|
252
|
+
@header.to_s! { "testing" }
|
253
|
+
@header.to_raw.should_not == proc { "testing" }
|
254
|
+
@header.to_raw[:random].should_not == "testing"
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
it "takes an optional argument specifying the raw header name to use, without side-effects" do
|
259
|
+
@header.to_s!("test").should_not == @full_header_string
|
260
|
+
@header.to_s!("test").should == "test#{@separator} #{@header_value}"
|
261
|
+
@header.to_s!.should == @full_header_string
|
262
|
+
@header.to_s!.should_not == "test#{@separator} #{@header_value}"
|
263
|
+
end
|
264
|
+
|
265
|
+
it "ignores the given block if there is an explicit raw header name" do
|
266
|
+
@header.to_s("test") { "foo" }.should_not == "foo#{@separator} #{@header_value}"
|
267
|
+
@header.to_s("test") { "foo" }.should == "test#{@separator} #{@header_value}"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "test_helper"
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe Redhead::String do
|
4
|
+
before(:each) do
|
5
|
+
@string_content = "Lorem ipsum dolor sit amet."
|
6
|
+
@string = "A-Header-Value: value\n\n#{@string_content}"
|
7
|
+
@rh_string = Redhead::String[@string]
|
8
|
+
@copy_rh_string = Redhead::String[@string.clone]
|
9
|
+
end
|
10
|
+
|
11
|
+
context "as a class" do
|
12
|
+
describe "self.[]" do
|
13
|
+
it "is equal (==) in result to using .new" do
|
14
|
+
Redhead::String[@string].should == Redhead::String.new(@string)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "self.new" do
|
19
|
+
context "with a given block:" do
|
20
|
+
it "uses the given block as to_key" do
|
21
|
+
Redhead::String.new(@string) { :foo }.headers.first.key.should == :foo
|
22
|
+
end
|
23
|
+
|
24
|
+
it "sets the given block as the HeaderSet's to_key" do
|
25
|
+
# note: Proc#== bug!
|
26
|
+
blk = proc { :foo }
|
27
|
+
Redhead::String.new(@string, &blk).headers.to_key.should == blk
|
28
|
+
end
|
29
|
+
|
30
|
+
it "sets each individual header's to_key to the given block" do
|
31
|
+
# note: Proc#== bug!
|
32
|
+
blk = proc { :foo }
|
33
|
+
Redhead::String.new(@string, &blk).headers.each { |header| header.to_key.should == blk }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context "before any modifications:" do
|
40
|
+
describe "#to_s" do
|
41
|
+
it "returns a proper String instance" do
|
42
|
+
@rh_string.to_s.class.should == String
|
43
|
+
end
|
44
|
+
|
45
|
+
it "is the contents of the header-less string" do
|
46
|
+
@rh_string.to_s.should == @string_content
|
47
|
+
end
|
48
|
+
|
49
|
+
it "is not in fact the same object as its contained string" do
|
50
|
+
@rh_string.to_s.equal?(@string_content).should be_false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#headers" do
|
56
|
+
it "returns a Redhead::HeaderSet object" do
|
57
|
+
@rh_string.headers.is_a?(Redhead::HeaderSet).should be_true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "provides regular String methods" do
|
62
|
+
String.instance_methods(false).each do |m|
|
63
|
+
@rh_string.respond_to?(m).should be_true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "modifies its containing string with bang-methods" do
|
68
|
+
orig = @rh_string.to_s.dup
|
69
|
+
@rh_string.reverse!
|
70
|
+
@rh_string.to_s.should == orig.reverse
|
71
|
+
@rh_string.reverse!
|
72
|
+
|
73
|
+
orig = @rh_string.to_s.dup
|
74
|
+
@rh_string.upcase!
|
75
|
+
@rh_string.to_s.should == orig.upcase
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#==" do
|
79
|
+
it "returns true if the two Redhead strings contain equal headersets (using HeaderSet#==) and the same string content (using String#==)" do
|
80
|
+
@rh_string.should == @rh_string
|
81
|
+
@copy_rh_string.should == @rh_string
|
82
|
+
|
83
|
+
# change the copy
|
84
|
+
@copy_rh_string.headers[:a_header_value] = "something"
|
85
|
+
@other_rh_string = @copy_rh_string
|
86
|
+
|
87
|
+
@rh_string.headers.should_not == @other_rh_string.headers
|
88
|
+
@rh_string.string.should == @other_rh_string.string
|
89
|
+
@rh_string.should_not == @other_rh_string
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe %Q{#headers!(:a => { :raw => "random raw", :key => "random key" })} do
|
94
|
+
it %Q{modifies the header for key :a by calling raw="random raw", and key="random_key"} do
|
95
|
+
header = @rh_string.headers[:a_header_value]
|
96
|
+
header.raw.should_not == "random raw"
|
97
|
+
header.key.should_not == "random key"
|
98
|
+
|
99
|
+
@rh_string.headers!(:a_header_value => { :raw => "random raw", :key => "random key" })
|
100
|
+
header.raw.should == "random raw"
|
101
|
+
header.key.should == "random key"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "ignores keys with no matching header" do
|
105
|
+
expect { @rh_string.headers!(:lorem_ipsum_dolor_sit_amettttt => {}) }.to_not raise_error
|
106
|
+
end
|
107
|
+
|
108
|
+
it "returns only the changed headers" do
|
109
|
+
@rh_string.headers!(:lorem_ipsum_dolor_sit_amet => {}).empty?.should be_true
|
110
|
+
@rh_string.headers!(:a_header_value => {}).empty?.should_not be_true
|
111
|
+
@rh_string.headers!(:a_header_value => {}).to_a.length.should == 1
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "redhead"
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redhead
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Prescott
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-04-22 00:00:00.000000000 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
requirement: &73758240 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *73758240
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rspec
|
28
|
+
requirement: &73758020 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *73758020
|
37
|
+
description: String header metadata.
|
38
|
+
email:
|
39
|
+
- adam@aprescott.com
|
40
|
+
executables: []
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- lib/redhead/header.rb
|
45
|
+
- lib/redhead/redhead_string.rb
|
46
|
+
- lib/redhead/header_set.rb
|
47
|
+
- lib/redhead.rb
|
48
|
+
- test/redhead_spec.rb
|
49
|
+
- test/redhead_string_spec.rb
|
50
|
+
- test/test_helper.rb
|
51
|
+
- test/header_set_spec.rb
|
52
|
+
- test/header_spec.rb
|
53
|
+
- LICENSE
|
54
|
+
- Gemfile
|
55
|
+
- rakefile
|
56
|
+
- README.md
|
57
|
+
has_rdoc: true
|
58
|
+
homepage: https://github.com/aprescott/redhead
|
59
|
+
licenses: []
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 1.6.2
|
79
|
+
signing_key:
|
80
|
+
specification_version: 3
|
81
|
+
summary: String header metadata.
|
82
|
+
test_files:
|
83
|
+
- test/redhead_spec.rb
|
84
|
+
- test/redhead_string_spec.rb
|
85
|
+
- test/test_helper.rb
|
86
|
+
- test/header_set_spec.rb
|
87
|
+
- test/header_spec.rb
|