roadforest 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/examples/file-management.rb +98 -0
  2. data/lib/roadforest/application/dispatcher.rb +54 -0
  3. data/lib/roadforest/application/parameters.rb +39 -0
  4. data/lib/roadforest/application/path-provider.rb +18 -0
  5. data/lib/roadforest/application/route-adapter.rb +24 -0
  6. data/lib/roadforest/application/services-host.rb +10 -0
  7. data/lib/roadforest/application.rb +42 -0
  8. data/lib/roadforest/blob-model.rb +56 -0
  9. data/lib/roadforest/content-handling/engine.rb +113 -0
  10. data/lib/roadforest/content-handling/media-type.rb +222 -0
  11. data/lib/roadforest/content-handling/type-handlers/jsonld.rb +172 -0
  12. data/lib/roadforest/http/adapters/excon.rb +47 -0
  13. data/lib/roadforest/http/graph-response.rb +20 -0
  14. data/lib/roadforest/http/graph-transfer.rb +112 -0
  15. data/lib/roadforest/http/message.rb +91 -0
  16. data/lib/roadforest/model.rb +151 -0
  17. data/lib/roadforest/models.rb +2 -0
  18. data/lib/roadforest/rdf/context-fascade.rb +25 -0
  19. data/lib/roadforest/rdf/document.rb +23 -0
  20. data/lib/roadforest/rdf/focus-list.rb +19 -0
  21. data/lib/roadforest/rdf/focus-wrapping.rb +30 -0
  22. data/lib/roadforest/rdf/graph-copier.rb +16 -0
  23. data/lib/roadforest/rdf/graph-focus.rb +95 -0
  24. data/lib/roadforest/rdf/graph-reading.rb +145 -0
  25. data/lib/roadforest/rdf/graph-store.rb +217 -0
  26. data/lib/roadforest/rdf/investigation.rb +90 -0
  27. data/lib/roadforest/rdf/normalization.rb +150 -0
  28. data/lib/roadforest/rdf/parcel.rb +47 -0
  29. data/lib/roadforest/rdf/post-focus.rb +35 -0
  30. data/lib/roadforest/rdf/resource-pattern.rb +60 -0
  31. data/lib/roadforest/rdf/resource-query.rb +58 -0
  32. data/lib/roadforest/rdf/source-rigor/credence/any.rb +9 -0
  33. data/lib/roadforest/rdf/source-rigor/credence/none-if-role-absent.rb +19 -0
  34. data/lib/roadforest/rdf/source-rigor/credence/role-if-available.rb +19 -0
  35. data/lib/roadforest/rdf/source-rigor/credence-annealer.rb +22 -0
  36. data/lib/roadforest/rdf/source-rigor/credence.rb +29 -0
  37. data/lib/roadforest/rdf/source-rigor/http-investigator.rb +20 -0
  38. data/lib/roadforest/rdf/source-rigor/investigator.rb +17 -0
  39. data/lib/roadforest/rdf/source-rigor/null-investigator.rb +10 -0
  40. data/lib/roadforest/rdf/source-rigor.rb +44 -0
  41. data/lib/roadforest/rdf/update-focus.rb +73 -0
  42. data/lib/roadforest/rdf/vocabulary.rb +11 -0
  43. data/lib/roadforest/rdf.rb +6 -0
  44. data/lib/roadforest/remote-host.rb +96 -0
  45. data/lib/roadforest/resource/handlers.rb +43 -0
  46. data/lib/roadforest/resource/http/form-parsing.rb +81 -0
  47. data/lib/roadforest/resource/rdf/leaf-item.rb +21 -0
  48. data/lib/roadforest/resource/rdf/list.rb +19 -0
  49. data/lib/roadforest/resource/rdf/parent-item.rb +26 -0
  50. data/lib/roadforest/resource/rdf/read-only.rb +100 -0
  51. data/lib/roadforest/resource/rdf.rb +4 -0
  52. data/lib/roadforest/resource/role/has-children.rb +22 -0
  53. data/lib/roadforest/resource/role/writable.rb +43 -0
  54. data/lib/roadforest/server.rb +3 -0
  55. data/lib/roadforest/test-support/dispatcher-facade.rb +77 -0
  56. data/lib/roadforest/test-support/http-client.rb +151 -0
  57. data/lib/roadforest/test-support/matchers.rb +67 -0
  58. data/lib/roadforest/test-support/remote-host.rb +23 -0
  59. data/lib/roadforest/test-support/trace-formatter.rb +140 -0
  60. data/lib/roadforest/test-support.rb +2 -0
  61. data/lib/roadforest/utility/class-registry.rb +49 -0
  62. data/lib/roadforest.rb +2 -0
  63. data/spec/client.rb +152 -0
  64. data/spec/credence-annealer.rb +44 -0
  65. data/spec/graph-copier.rb +87 -0
  66. data/spec/graph-store.rb +142 -0
  67. data/spec/media-types.rb +14 -0
  68. data/spec/rdf-parcel.rb +158 -0
  69. data/spec/update-focus.rb +117 -0
  70. data/spec_support/gem_test_suite.rb +0 -0
  71. metadata +241 -0
@@ -0,0 +1,140 @@
1
+ module RoadForest
2
+ class TraceFormatter
3
+ DECISION_NAMES = {
4
+ :b13 => "Service available?",
5
+ :b12 => "Known method?",
6
+ :b11 => "URI too long?",
7
+ :b10 => "Method allowed?",
8
+ :b9 => "Content-MD5 present?",
9
+ :b9a => "Content-MD5 valid?",
10
+ :b9b => "Malformed?",
11
+ :b8 => "Authorized?",
12
+ :b7 => "Forbidden?",
13
+ :b6 => "Okay Content-* Headers?",
14
+ :b5 => "Known Content-Type?",
15
+ :b4 => "Req Entity Too Large?",
16
+ :b3 => "OPTIONS?",
17
+ :c3 => "Accept exists?",
18
+ :c4 => "Acceptable media type available?",
19
+ :d4 => "Accept-Language exists?",
20
+ :d5 => "Acceptable language available?",
21
+ :e5 => "Accept-Charset exists?",
22
+ :e6 => "Acceptable Charset available?",
23
+ :f6 => "Accept-Encoding exists? (also, set content-type header here, now that charset is chosen)",
24
+ :f7 => "Acceptable encoding available?",
25
+ :g7 => "Resource exists?",
26
+ :g8 => "If-Match exists?",
27
+ :g9 => "If-Match: * exists?",
28
+ :g11 => "ETag in If-Match",
29
+ :h7 => "If-Match exists?",
30
+ :h10 => "If-Unmodified-Since exists?",
31
+ :h12 => "Last-Modified > I-UM-S?",
32
+ :i4 => "Moved permanently? (apply PUT to different URI)",
33
+ :i7 => "PUT?",
34
+ :i12 => "If-none-match exists?",
35
+ :i13 => "If-none-match: * exists?",
36
+ :j18 => "GET or HEAD?",
37
+ :k5 => "Moved permanently?",
38
+ :k7 => "Previously existed?",
39
+ :k13 => "Etag in if-none-match?",
40
+ :l5 => "Moved temporarily?",
41
+ :l7 => "POST?",
42
+ :l13 => "If-Modified-Since exists?",
43
+ :l15 => "IMS > Now?",
44
+ :l17 => "Last-Modified > IMS?",
45
+ :m5 => "POST?",
46
+ :m7 => "Server allows POST to missing resource?",
47
+ :m16 => "DELETE?",
48
+ :m20 => "DELETE enacted immediately? (Also where DELETE is forced.)",
49
+ :m20b => "Did the DELETE complete?",
50
+ :n5 => "Server allows POST to missing resource?",
51
+ :n11 => "Redirect?",
52
+ :n16 => "POST?",
53
+ :o14 => "Conflict?",
54
+ :o16 => "PUT?",
55
+ :o18 => "Multiple representations? Also where body generation for GET and HEAD is done.",
56
+ :o18b => "Multiple choices?",
57
+ :o20 => "Response includes an entity?",
58
+ :p3 => "Conflict?",
59
+ :p11 => "New resource?",
60
+ }
61
+
62
+ def initialize(trace)
63
+ @trace = trace
64
+ end
65
+
66
+ def to_s
67
+ Grouper.new(@trace).to_a.join("\n")
68
+ end
69
+
70
+ class Grouper
71
+ include Enumerable
72
+
73
+ def initialize(trace)
74
+ @trace = trace
75
+ end
76
+
77
+ def format_attempt(attempt)
78
+ unless attempt.length == 2 and
79
+ attempt[0][:type] == :attempt and
80
+ attempt[1][:type] == :result
81
+ raise "Can't format attempt: #{attempt.inspect}"
82
+ end
83
+ name= attempt[0][:name]
84
+ source= attempt[0][:source]
85
+ result= attempt[1][:value]
86
+
87
+ if source.nil?
88
+ " #{name} => #{result.inspect}"
89
+ else
90
+ "\n #{name}\n #{source}\n => #{result.inspect}"
91
+ end
92
+ end
93
+
94
+ def format_request(request)
95
+ "\nRequest:\n #{request[:method]} #{request[:path]}\n#{request[:headers].map do |name, value|
96
+ " #{name}: #{value}"
97
+ end.join("\n")}#{request[:body].empty? ? "" : "\n\n #{request[:body]}"}\n.\n"
98
+ end
99
+
100
+ def format_response(response)
101
+ "\nResponse:\n #{response[:code]}\n#{response[:headers].map do |name, value|
102
+ " #{name}: #{value}"
103
+ end.join("\n")}#{response[:body].empty? ? "" : "\n\n #{response[:body]}"}\n.\n"
104
+ end
105
+
106
+ def format_decision(item)
107
+ "\nDecision: #{DECISION_NAMES[item[:decision]]} (#{item[:decision]})"
108
+ end
109
+
110
+ def each
111
+ enum = @trace.each
112
+
113
+ group = []
114
+ loop do
115
+ begin
116
+ item = enum.next
117
+ case item[:type]
118
+ when :request
119
+ yield format_request(item)
120
+ when :response
121
+ yield format_response(item)
122
+ when :attempt
123
+ group << item
124
+ when :result
125
+ group << item
126
+ yield format_attempt(group)
127
+ group = []
128
+ when :decision
129
+ yield format_decision(item)
130
+ else
131
+ raise "Don't know trace entry type: #{item.inspect}"
132
+ end
133
+ rescue StopIteration
134
+ break
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,2 @@
1
+ require 'roadforest/test-support/remote-host'
2
+ require 'roadforest/test-support/matchers'
@@ -0,0 +1,49 @@
1
+ module RoadForest
2
+ module Utility
3
+ class ClassRegistry
4
+ module Registrar
5
+ def registry
6
+ @registry ||= ClassRegistry.new(self)
7
+ end
8
+
9
+ def register(name)
10
+ registrar.registry.add(name, self)
11
+ end
12
+
13
+ def [](name)
14
+ registrar.registry.get(name)
15
+ end
16
+
17
+ def self.extended(mod)
18
+ (
19
+ class << mod; self; end
20
+ ).instance_exec(mod) do |mod|
21
+ define_method :registrar do
22
+ mod
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def initialize(registrar)
29
+ if registrar.respond_to?(:registry_purpose)
30
+ @purpose = registrar.registry_purpose
31
+ else
32
+ @purpose = registrar.name
33
+ end
34
+ @classes = {}
35
+ end
36
+
37
+ def add(name, klass)
38
+ @classes[name.to_sym] = klass
39
+ @classes[name.to_s] = klass
40
+ end
41
+
42
+ def get(name)
43
+ @classes.fetch(name)
44
+ rescue KeyError
45
+ raise "No #@purpose class registered as name: #{name.inspect}"
46
+ end
47
+ end
48
+ end
49
+ end
data/lib/roadforest.rb ADDED
@@ -0,0 +1,2 @@
1
+ module RoadForest
2
+ end
data/spec/client.rb ADDED
@@ -0,0 +1,152 @@
1
+ require 'roadforest/server'
2
+ require 'roadforest/test-support'
3
+
4
+ require 'examples/file-management'
5
+
6
+ describe RoadForest::RemoteHost do
7
+ let :destination_dir do
8
+ "spec_support/destination"
9
+ end
10
+
11
+ let :source_path do
12
+ "spec_support/test-file.txt"
13
+ end
14
+
15
+ let :services do
16
+ FileManagementExample::ServicesHost.new.tap do |host|
17
+ host.file_records = [
18
+ FileManagementExample::FileRecord.new("one", false),
19
+ FileManagementExample::FileRecord.new("two", false),
20
+ FileManagementExample::FileRecord.new("three", false)
21
+ ]
22
+ host.destination_dir = destination_dir
23
+ end
24
+ end
25
+
26
+ let :server do
27
+ RoadForest::TestSupport::RemoteHost.new(FileManagementExample::Application.new("http://roadforest.test-domain.com/", services))
28
+ end
29
+
30
+ def dump_trace
31
+ tracing = true
32
+ tracing = false
33
+ if tracing
34
+ RoadForest::TestSupport::FSM.dump_trace
35
+ end
36
+ end
37
+
38
+ before :each do
39
+ RoadForest::TestSupport::FSM.trace_on
40
+ end
41
+
42
+ before :each do
43
+ require 'fileutils'
44
+ FileUtils.rm_f(destination_dir)
45
+ FileUtils.mkdir_p(destination_dir)
46
+ end
47
+
48
+ describe "raw put of file data" do
49
+ before :each do
50
+ @destination = nil
51
+ server.getting do |graph|
52
+ items = graph.all(:skos, "hasTopConcept")
53
+
54
+ unresolved = items.find do |nav_item|
55
+ nav_item[:skos, "label"] == "Unresolved"
56
+ end
57
+
58
+ target = unresolved.first(:foaf, "page")
59
+
60
+ @destination = target.first(:lc, "needs").as_list.first[:lc, "contents"]
61
+ end
62
+
63
+ unless @destination.nil?
64
+ File::open(source_path) do |file|
65
+ server.put_file(@destination, "text/plain", file)
66
+ end
67
+ end
68
+ end
69
+
70
+ it "should be able to format traces correctly" do
71
+ RoadForest::TestSupport::FSM.trace_dump.should =~ /Decision/
72
+ end
73
+
74
+ it "should set destination" do
75
+ @destination.to_context.to_s.should == "http://roadforest.test-domain.com/files/one"
76
+ end
77
+
78
+ it "should deliver file to destination path" do
79
+ File::read(File::join(destination_dir, "one")).should ==
80
+ File::read(source_path)
81
+ end
82
+ end
83
+
84
+ describe "posting data to server" do
85
+ before :each do
86
+ begin
87
+ server.posting do |graph|
88
+ items = graph.all(:skos, "hasTopConcept")
89
+
90
+ unresolved = items.find do |nav_item|
91
+ nav_item[:skos, "label"] == "Unresolved"
92
+ end
93
+
94
+ target = unresolved.first(:foaf, "page")
95
+
96
+ target.post_to do |new_need|
97
+ new_need[[:lc, "name"]] = "lawyers/guns/money"
98
+ end
99
+ end
100
+ ensure
101
+ dump_trace
102
+ end
103
+ end
104
+
105
+ it "should change the server state" do
106
+ services.file_records.find do |record|
107
+ record.name == "lawyers/guns/money"
108
+ end.should be_an_instance_of FileManagementExample::FileRecord
109
+ end
110
+ end
111
+
112
+ describe "putting data to server" do
113
+ before :each do
114
+ server.putting do |graph|
115
+ items = graph.all(:skos, "hasTopConcept")
116
+
117
+ unresolved = items.find do |nav_item|
118
+ nav_item[:skos, "label"] == "Unresolved"
119
+ end
120
+
121
+ target = unresolved.first(:foaf, "page")
122
+
123
+ needs = target.first(:lc, "needs").as_list
124
+
125
+ needs.each do |need|
126
+ need[[:lc, "resolved"]] = true
127
+ end
128
+ end
129
+ end
130
+
131
+ it "should change the server state" do
132
+ services.file_records.each do |record|
133
+ record.resolved.should == true
134
+ end
135
+ end
136
+
137
+ it "should extract data from server responses" do
138
+ server.should match_query do
139
+ pattern(:subject, [:lc, "path"], nil)
140
+ pattern(:subject, [:lc, "file"], nil)
141
+ end
142
+ end
143
+
144
+ it "should return correct content-type" do
145
+ #test_server.http_exchanges.each{|ex| puts ex.response.body}
146
+ server.http_exchanges.should_not be_empty
147
+ server.http_exchanges.each do |exchange|
148
+ exchange.response.headers["Content-Type"].should == "application/ld+json"
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,44 @@
1
+ require 'roadforest/rdf/source-rigor/credence-annealer'
2
+ require 'roadforest/rdf/graph-store'
3
+ require 'timeout'
4
+
5
+ describe RoadForest::RDF::SourceRigor::CredenceAnnealer do
6
+ let :graph do
7
+ RoadForest::RDF::GraphStore.new
8
+ end
9
+
10
+ subject :annealer do
11
+ RoadForest::RDF::SourceRigor::CredenceAnnealer.new(graph)
12
+ end
13
+
14
+ it "should run it's block at least once" do
15
+ tested = false
16
+ annealer.resolve do
17
+ tested = true
18
+ end
19
+ tested.should be_true
20
+ end
21
+
22
+ it "should re-run it's block until the GraphStore settles" do
23
+ graph.stub(:quiet_impulse?).and_return(false, false, true)
24
+
25
+ times_run = 0
26
+ annealer.resolve do
27
+ times_run += 1
28
+ end
29
+
30
+ times_run.should == 3
31
+ end
32
+
33
+ it "should produce an error in some infinite-loop style situation" do
34
+ graph.stub(:quiet_impulse?).and_return(false)
35
+
36
+ expect do
37
+ Timeout::timeout(1) do
38
+ annealer.resolve do
39
+ end
40
+ end
41
+ end.to raise_error(/Annealing failed/)
42
+ end
43
+
44
+ end
@@ -0,0 +1,87 @@
1
+ require 'roadforest/test-support/matchers'
2
+ require 'roadforest/rdf/graph-copier'
3
+
4
+ #Leaving notes since being interrupted
5
+ #
6
+ #GC needs to tessellate the graph in the same way that Parceller should -
7
+ #probably should make sure that works first. Basically same resource should ==
8
+ #same subgraph copied, since otherwise client omission of a property isn't
9
+ #distinguishable from the intent to delete it. Only copy once so that you don't
10
+ #overwrite client changes.
11
+ #
12
+ #Also: "single put" involves a whole extra level of server code to accept the
13
+ #put, parcel it out, confirm IMS headers across everyone... so that's a v2
14
+ #feature
15
+
16
+ describe RoadForest::RDF::GraphCopier, :pending => "review of API" do
17
+ class TestVoc < ::RDF::Vocabulary("http://test.com/");end
18
+
19
+ let :start_subject do
20
+ RDF::Node.new
21
+ end
22
+
23
+ let :other_subject do
24
+ RDF::Node.new
25
+ end
26
+
27
+ let :starting_statements do
28
+ [
29
+ [start_subject, TestVoc[:a], 7],
30
+ [start_subject, TestVoc[:other], other_subject]
31
+ ]
32
+ end
33
+
34
+ let :other_statements do
35
+ [
36
+ [other_subject, TestVoc[:a], 13]
37
+ ]
38
+ end
39
+
40
+ let :source_graph do
41
+ ::RDF::Graph.new.tap do |graph|
42
+ starting_statements.each do |stmt|
43
+ graph << stmt
44
+ end
45
+
46
+ other_statements.each do |stmt|
47
+ graph << stmt
48
+ end
49
+ end
50
+ end
51
+
52
+ let :document do
53
+ RoadForest::RDF::Document.new.tap do |doc|
54
+ doc.source =
55
+ doc.body_string = source_graph.dump(:rdfa)
56
+ end
57
+ end
58
+
59
+ let :copier do
60
+ RoadForest::RDF::GraphCopier.new.tap do |copier|
61
+ copier.source_graph = source_graph
62
+ copier.subject = start_subject
63
+ end
64
+ end
65
+
66
+ it "reads the notes above, unless it wants the hose again" do
67
+ fail "shoulda read the notes"
68
+ end
69
+
70
+ it "should have a target graph" do
71
+ copier.target_graph.should be_an_instance_of(::RDF::Graph)
72
+ end
73
+
74
+ it "should have statements about starting subject" do
75
+ statements_from_graph(copier.target_graph).that_match_query(:subject => start_subject).should be_equivalent_to(starting_statements)
76
+ end
77
+
78
+ it "should not have statements about other subject" do
79
+ copier.target_graph.query(:subject => other_subject).to_a.should be_empty
80
+ end
81
+
82
+ it "should get statements about other subject" do
83
+ copier[[:testvoc, :other]]
84
+
85
+ statements_from_graph(copier.target_graph).that_match_query(:subject => other_subject).should be_equivalent_to(other_statements)
86
+ end
87
+ end
@@ -0,0 +1,142 @@
1
+ require 'rdf'
2
+ #require 'rdf/rdfa'
3
+ require 'roadforest/rdf/document'
4
+ require 'roadforest/rdf/graph-store'
5
+
6
+ describe RoadForest::RDF do
7
+ let :source_rigor do
8
+ RoadForest::RDF::SourceRigor.new.tap do |skept|
9
+ skept.policy_list(:may_subject)
10
+ skept.investigator_list(:null)
11
+ end
12
+ end
13
+
14
+ let :graph_store do
15
+ RoadForest::RDF::GraphStore.new
16
+ end
17
+
18
+ #merging graphs
19
+
20
+ describe RoadForest::RDF::GraphStore do
21
+ let :root_body do
22
+ store = RoadForest::RDF::GraphStore.new
23
+ step = RoadForest::RDF::GraphFocus.new("http://lrdesign.com/test-rdf", store, source_rigor)
24
+ step[[:foaf, :givenname]] = "Lester"
25
+ step[[:dc, :date]] = Time.now
26
+ step = step.node_at([:dc, :related], "http://lrdesign.com/test-rdf/sub")
27
+ step[[:dc, :date]] = Time.now
28
+
29
+ store.graph_dump(:rdfa)
30
+ end
31
+
32
+ let :second_body do
33
+ store = RoadForest::RDF::GraphStore.new
34
+ step = RoadForest::RDF::GraphFocus.new("http://lrdesign.com/test-rdf", store, source_rigor)
35
+ step[[:foaf, :givenname]] = "Foster"
36
+ step[[:dc, :date]] = Time.now
37
+
38
+ store.graph_dump(:rdfa)
39
+ end
40
+
41
+ let :first_doc do
42
+ RoadForest::RDF::Document.new.tap do |doc|
43
+ doc.source = "http://lrdesign.com/test-rdf"
44
+ doc.body_string = root_body
45
+ end
46
+ end
47
+
48
+ let :second_doc do
49
+ RoadForest::RDF::Document.new.tap do |doc|
50
+ doc.source = "http://lrdesign.com/test-rdf"
51
+ doc.body_string = second_body
52
+ end
53
+ end
54
+
55
+ before :each do
56
+ graph_store.insert_document(first_doc)
57
+ end
58
+
59
+ it "should transmit properties" do
60
+ step = RoadForest::RDF::GraphFocus.new("http://lrdesign.com/test-rdf", graph_store, source_rigor)
61
+ step[:dc, :date].should be_an_instance_of(Time)
62
+ end
63
+
64
+ it "should replace previous statements from same URL" do
65
+ expect{
66
+ graph_store.insert_document(second_doc)
67
+ }.to change{
68
+ RoadForest::RDF::GraphFocus.new("http://lrdesign.com/test-rdf", graph_store, source_rigor)[:foaf, :givenname]
69
+ }
70
+ end
71
+ end
72
+
73
+ describe RoadForest::RDF::GraphFocus do
74
+ let :main_subject do
75
+ RDF::URI.new("http://test.com/main")
76
+ end
77
+
78
+ let :creator do
79
+ RDF::Node.new
80
+ end
81
+
82
+ let :root do
83
+ RDF::Node.new
84
+ end
85
+
86
+ before :each do
87
+ graph_store.add_statement(root, [:dc, :relation], main_subject)
88
+ graph_store.add_statement(creator, [:foaf, :familyName], "Lester")
89
+ graph_store.add_statement(creator, [:foaf, :givenname], "Judson")
90
+ graph_store.add_statement(main_subject, [:dc, :creator], creator)
91
+ graph_store.add_statement(main_subject, [:dc, :date], Time.now)
92
+ end
93
+
94
+ let :step do
95
+ RoadForest::RDF::GraphFocus.new(main_subject, graph_store, source_rigor)
96
+ end
97
+
98
+ it "should enumerate forward properties" do
99
+ step.forward_properties.should include([:dc, :creator])
100
+ step.forward_properties.should include([:dc, :date])
101
+ step.forward_properties.should_not include([:foaf, :familyName])
102
+ step.forward_properties.should_not include([:dc, :relation])
103
+ end
104
+
105
+ it "should get values for properties" do
106
+ step.get(:dc, :creator).rdf.should == creator
107
+ step.get(:dc, :date).should be_an_instance_of(Time)
108
+ step[:dc, :date].should be_an_instance_of(Time)
109
+ step[[:dc, :date]].should be_an_instance_of(Time)
110
+ end
111
+
112
+ it "should enumerate reverse properties" do
113
+ step.reverse_properties.should include([:dc, :relation])
114
+ step.reverse_properties.should_not include([:dc, :creator])
115
+ end
116
+
117
+ it "should get values for inbound properties" do
118
+ step.rev(:dc, :relation).rdf.should == root
119
+ end
120
+
121
+ it "should walk forward to properties" do
122
+ step[:dc,:creator][:foaf,:givenname].should == "Judson"
123
+ end
124
+
125
+ it "should be able to add properties with []=", :pending => "Should GraphStores accept local writes?" do
126
+ step[[:dc, :dateCopyrighted]] = Time.now #slightly ugly syntax
127
+ step[:dc, :dateCopyrighted].should be_an_instance_of(Time)
128
+ RDF::Query.new do |query|
129
+ query.pattern [:subject, RDF::DC.dateCopyrighted, :value]
130
+ end.execute(graph_store).should_not be_empty
131
+ end
132
+
133
+ it "should be able to add properties with set", :pending => "Should GraphStores accept local writes?" do
134
+ step.set(:dc, :dateCopyrighted, Time.now)
135
+ step[:dc, :dateCopyrighted].should be_an_instance_of(Time)
136
+ RDF::Query.new do |query|
137
+ query.pattern [:subject, RDF::DC.dateCopyrighted, :value]
138
+ store.execute(graph_store).should_not be_empty
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,14 @@
1
+ require 'roadforest/content-handling/media-type'
2
+ describe RoadForest::ContentHandling::MediaType do
3
+ let :accepted_list do
4
+ RoadForest::ContentHandling::MediaTypeList.build("text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5")
5
+ end
6
+
7
+ let :provided_list do
8
+ RoadForest::ContentHandling::MediaTypeList.build("text/html;q=0.9;rdfa=true, application/json+ld;q=0.4")
9
+ end
10
+
11
+ it "should find best match" do
12
+ accepted_list.best_match_from(provided_list).should =~ "text/html"
13
+ end
14
+ end