roadforest 0.0.1

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.
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