]> git.openstreetmap.org Git - rails.git/blob - test/controllers/old_node_controller_test.rb
6e90773fabecda1185a731ce8d6b4ccc6ca09b2f
[rails.git] / test / controllers / old_node_controller_test.rb
1 require 'test_helper'
2 require 'old_node_controller'
3
4 class OldNodeControllerTest < ActionController::TestCase
5   api_fixtures
6
7   #
8   # TODO: test history
9   #
10
11   ##
12   # test all routes which lead to this controller
13   def test_routes
14     assert_routing(
15       { :path => "/api/0.6/node/1/history", :method => :get },
16       { :controller => "old_node", :action => "history", :id => "1" }
17     )
18     assert_routing(
19       { :path => "/api/0.6/node/1/2", :method => :get },
20       { :controller => "old_node", :action => "version", :id => "1", :version => "2" }
21     )
22     assert_routing(
23       { :path => "/api/0.6/node/1/2/redact", :method => :post },
24       { :controller => "old_node", :action => "redact", :id => "1", :version => "2" }
25     )
26   end
27
28   ##
29   # test the version call by submitting several revisions of a new node
30   # to the API and ensuring that later calls to version return the
31   # matching versions of the object.
32   #
33   ##
34   # FIXME Move this test to being an integration test since it spans multiple controllers
35   def test_version
36     ## First try this with a non-public user
37     basic_authorization(users(:normal_user).email, "test")
38     changeset_id = changesets(:normal_user_first_change).id
39
40     # setup a simple XML node
41     xml_doc = current_nodes(:visible_node).to_xml
42     xml_node = xml_doc.find("//osm/node").first
43     nodeid = current_nodes(:visible_node).id
44
45     # keep a hash of the versions => string, as we'll need something
46     # to test against later
47     versions = {}
48
49     # save a version for later checking
50     versions[xml_node['version']] = xml_doc.to_s
51
52     # randomly move the node about
53     20.times do
54       # move the node somewhere else
55       xml_node['lat'] = precision(rand * 180 -  90).to_s
56       xml_node['lon'] = precision(rand * 360 - 180).to_s
57       with_controller(NodeController.new) do
58         content xml_doc
59         put :update, :id => nodeid
60         assert_response :forbidden, "Should have rejected node update"
61         xml_node['version'] = @response.body.to_s
62       end
63       # save a version for later checking
64       versions[xml_node['version']] = xml_doc.to_s
65     end
66
67     # add a bunch of random tags
68     30.times do
69       xml_tag = XML::Node.new("tag")
70       xml_tag['k'] = random_string
71       xml_tag['v'] = random_string
72       xml_node << xml_tag
73       with_controller(NodeController.new) do
74         content xml_doc
75         put :update, :id => nodeid
76         assert_response :forbidden,
77                         "should have rejected node #{nodeid} (#{@response.body}) with forbidden"
78         xml_node['version'] = @response.body.to_s
79       end
80       # save a version for later checking
81       versions[xml_node['version']] = xml_doc.to_s
82     end
83
84     # probably should check that they didn't get written to the database
85
86     ## Now do it with the public user
87     basic_authorization(users(:public_user).email, "test")
88     changeset_id = changesets(:public_user_first_change).id
89
90     # setup a simple XML node
91     xml_doc = current_nodes(:node_with_versions).to_xml
92     xml_node = xml_doc.find("//osm/node").first
93     nodeid = current_nodes(:node_with_versions).id
94
95     # keep a hash of the versions => string, as we'll need something
96     # to test against later
97     versions = {}
98
99     # save a version for later checking
100     versions[xml_node['version']] = xml_doc.to_s
101
102     # randomly move the node about
103     20.times do
104       # move the node somewhere else
105       xml_node['lat'] = precision(rand * 180 -  90).to_s
106       xml_node['lon'] = precision(rand * 360 - 180).to_s
107       with_controller(NodeController.new) do
108         content xml_doc
109         put :update, :id => nodeid
110         assert_response :success
111         xml_node['version'] = @response.body.to_s
112       end
113       # save a version for later checking
114       versions[xml_node['version']] = xml_doc.to_s
115     end
116
117     # add a bunch of random tags
118     30.times do
119       xml_tag = XML::Node.new("tag")
120       xml_tag['k'] = random_string
121       xml_tag['v'] = random_string
122       xml_node << xml_tag
123       with_controller(NodeController.new) do
124         content xml_doc
125         put :update, :id => nodeid
126         assert_response :success,
127                         "couldn't update node #{nodeid} (#{@response.body})"
128         xml_node['version'] = @response.body.to_s
129       end
130       # save a version for later checking
131       versions[xml_node['version']] = xml_doc.to_s
132     end
133
134     # check all the versions
135     versions.keys.each do |key|
136       get :version, :id => nodeid, :version => key.to_i
137
138       assert_response :success,
139                       "couldn't get version #{key.to_i} of node #{nodeid}"
140
141       check_node = Node.from_xml(versions[key])
142       api_node = Node.from_xml(@response.body.to_s)
143
144       assert_nodes_are_equal check_node, api_node
145     end
146   end
147
148   def test_not_found_version
149     check_not_found_id_version(70000, 312344)
150     check_not_found_id_version(-1, -13)
151     check_not_found_id_version(nodes(:visible_node).id, 24354)
152     check_not_found_id_version(24356,   nodes(:visible_node).version)
153   end
154
155   def check_not_found_id_version(id, version)
156     get :version, :id => id, :version => version
157     assert_response :not_found
158   rescue ActionController::UrlGenerationError => ex
159     assert_match /No route matches/, ex.to_s
160   end
161
162   ##
163   # Test that getting the current version is identical to picking
164   # that version with the version URI call.
165   def test_current_version
166     check_current_version(current_nodes(:visible_node))
167     check_current_version(current_nodes(:used_node_1))
168     check_current_version(current_nodes(:used_node_2))
169     check_current_version(current_nodes(:node_used_by_relationship))
170     check_current_version(current_nodes(:node_with_versions))
171   end
172
173   ##
174   # test the redaction of an old version of a node, while not being
175   # authorised.
176   def test_redact_node_unauthorised
177     do_redact_node(nodes(:node_with_versions_v3),
178                    redactions(:example))
179     assert_response :unauthorized, "should need to be authenticated to redact."
180   end
181
182   ##
183   # test the redaction of an old version of a node, while being
184   # authorised as a normal user.
185   def test_redact_node_normal_user
186     basic_authorization(users(:public_user).email, "test")
187
188     do_redact_node(nodes(:node_with_versions_v3),
189                    redactions(:example))
190     assert_response :forbidden, "should need to be moderator to redact."
191   end
192
193   ##
194   # test that, even as moderator, the current version of a node
195   # can't be redacted.
196   def test_redact_node_current_version
197     basic_authorization(users(:moderator_user).email, "test")
198
199     do_redact_node(nodes(:node_with_versions_v4),
200                    redactions(:example))
201     assert_response :bad_request, "shouldn't be OK to redact current version as moderator."
202   end
203
204   ##
205   # test that redacted nodes aren't visible, regardless of
206   # authorisation except as moderator...
207   def test_version_redacted
208     node = nodes(:redacted_node_redacted_version)
209
210     get :version, :id => node.node_id, :version => node.version
211     assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
212
213     # not even to a logged-in user
214     basic_authorization(users(:public_user).email, "test")
215     get :version, :id => node.node_id, :version => node.version
216     assert_response :forbidden, "Redacted node shouldn't be visible via the version API, even when logged in."
217   end
218
219   ##
220   # test that redacted nodes aren't visible in the history
221   def test_history_redacted
222     node = nodes(:redacted_node_redacted_version)
223
224     get :history, :id => node.node_id
225     assert_response :success, "Redaction shouldn't have stopped history working."
226     assert_select "osm node[id='#{node.node_id}'][version='#{node.version}']", 0, "redacted node #{node.node_id} version #{node.version} shouldn't be present in the history."
227
228     # not even to a logged-in user
229     basic_authorization(users(:public_user).email, "test")
230     get :history, :id => node.node_id
231     assert_response :success, "Redaction shouldn't have stopped history working."
232     assert_select "osm node[id='#{node.node_id}'][version='#{node.version}']", 0, "redacted node #{node.node_id} version #{node.version} shouldn't be present in the history, even when logged in."
233   end
234
235   ##
236   # test the redaction of an old version of a node, while being
237   # authorised as a moderator.
238   def test_redact_node_moderator
239     node = nodes(:node_with_versions_v3)
240     basic_authorization(users(:moderator_user).email, "test")
241
242     do_redact_node(node, redactions(:example))
243     assert_response :success, "should be OK to redact old version as moderator."
244
245     # check moderator can still see the redacted data, when passing
246     # the appropriate flag
247     get :version, :id => node.node_id, :version => node.version
248     assert_response :forbidden, "After redaction, node should be gone for moderator, when flag not passed."
249     get :version, :id => node.node_id, :version => node.version, :show_redactions => 'true'
250     assert_response :success, "After redaction, node should not be gone for moderator, when flag passed."
251
252     # and when accessed via history
253     get :history, :id => node.node_id
254     assert_response :success, "Redaction shouldn't have stopped history working."
255     assert_select "osm node[id='#{node.node_id}'][version='#{node.version}']", 0, "node #{node.node_id} version #{node.version} should not be present in the history for moderators when not passing flag."
256     get :history, :id => node.node_id, :show_redactions => 'true'
257     assert_response :success, "Redaction shouldn't have stopped history working."
258     assert_select "osm node[id='#{node.node_id}'][version='#{node.version}']", 1, "node #{node.node_id} version #{node.version} should still be present in the history for moderators when passing flag."
259   end
260
261   # testing that if the moderator drops auth, he can't see the
262   # redacted stuff any more.
263   def test_redact_node_is_redacted
264     node = nodes(:node_with_versions_v3)
265     basic_authorization(users(:moderator_user).email, "test")
266
267     do_redact_node(node, redactions(:example))
268     assert_response :success, "should be OK to redact old version as moderator."
269
270     # re-auth as non-moderator
271     basic_authorization(users(:public_user).email, "test")
272
273     # check can't see the redacted data
274     get :version, :id => node.node_id, :version => node.version
275     assert_response :forbidden, "Redacted node shouldn't be visible via the version API."
276
277     # and when accessed via history
278     get :history, :id => node.node_id
279     assert_response :success, "Redaction shouldn't have stopped history working."
280     assert_select "osm node[id='#{node.node_id}'][version='#{node.version}']", 0, "redacted node #{node.node_id} version #{node.version} shouldn't be present in the history."
281   end
282
283   def do_redact_node(node, redaction)
284     get :version, :id => node.node_id, :version => node.version
285     assert_response :success, "should be able to get version #{node.version} of node #{node.node_id}."
286
287     # now redact it
288     post :redact, :id => node.node_id, :version => node.version, :redaction => redaction.id
289   end
290
291   def check_current_version(node_id)
292     # get the current version of the node
293     current_node = with_controller(NodeController.new) do
294       get :read, :id => node_id
295       assert_response :success, "cant get current node #{node_id}"
296       Node.from_xml(@response.body)
297     end
298     assert_not_nil current_node, "getting node #{node_id} returned nil"
299
300     # get the "old" version of the node from the old_node interface
301     get :version, :id => node_id, :version => current_node.version
302     assert_response :success, "cant get old node #{node_id}, v#{current_node.version}"
303     old_node = Node.from_xml(@response.body)
304
305     # check the nodes are the same
306     assert_nodes_are_equal current_node, old_node
307   end
308
309   ##
310   # returns a 16 character long string with some nasty characters in it.
311   # this ought to stress-test the tag handling as well as the versioning.
312   def random_string
313     letters = [['!', '"', '$', '&', ';', '@'],
314                ('a'..'z').to_a,
315                ('A'..'Z').to_a,
316                ('0'..'9').to_a].flatten
317     (1..16).map { |_i| letters[rand(letters.length)] }.join
318   end
319
320   ##
321   # truncate a floating point number to the scale that it is stored in
322   # the database. otherwise rounding errors can produce failing unit
323   # tests when they shouldn't.
324   def precision(f)
325     (f * GeoRecord::SCALE).round.to_f / GeoRecord::SCALE
326   end
327 end