1 # frozen_string_literal: true
7 class UploadsControllerTest < ActionDispatch::IntegrationTest
9 # test all routes which lead to this controller
12 { :path => "/api/0.6/changeset/1/upload", :method => :post },
13 { :controller => "api/changesets/uploads", :action => "create", :changeset_id => "1" }
17 def test_upload_when_unauthorized
18 changeset = create(:changeset)
19 node = create(:node, :latitude => 0, :longitude => 0)
24 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
29 post api_changeset_upload_path(changeset), :params => diff
31 assert_response :unauthorized
33 assert_no_changes_in changeset
36 assert_equal 1, node.version
37 assert_equal 0, node.latitude
38 assert_equal 0, node.longitude
41 def test_upload_by_private_user
42 user = create(:user, :data_public => false)
43 changeset = create(:changeset, :user => user)
44 node = create(:node, :latitude => 0, :longitude => 0)
49 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
54 auth_header = bearer_authorization_header user
56 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
58 assert_response :forbidden
60 assert_no_changes_in changeset
63 assert_equal 1, node.version
64 assert_equal 0, node.latitude
65 assert_equal 0, node.longitude
68 def test_upload_without_required_scope
70 changeset = create(:changeset, :user => user)
71 node = create(:node, :latitude => 0, :longitude => 0)
76 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
81 auth_header = bearer_authorization_header user, :scopes => %w[read_prefs]
83 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
85 assert_response :forbidden
87 assert_no_changes_in changeset
90 assert_equal 1, node.version
91 assert_equal 0, node.latitude
92 assert_equal 0, node.longitude
95 def test_upload_with_required_scope
97 changeset = create(:changeset, :user => user)
98 node = create(:node, :latitude => 0, :longitude => 0)
103 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
108 auth_header = bearer_authorization_header user, :scopes => %w[write_api]
110 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
112 assert_response :success
114 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
115 assert_dom "> node", 1 do
116 assert_dom "> @old_id", node.id.to_s
117 assert_dom "> @new_id", node.id.to_s
118 assert_dom "> @new_version", "2"
123 assert_equal 1, changeset.num_changes
124 assert_predicate changeset, :num_type_changes_in_sync?
125 assert_equal 1, changeset.num_modified_nodes
128 assert_equal 2, node.version
129 assert_equal 2 * GeoRecord::SCALE, node.latitude
130 assert_equal 1 * GeoRecord::SCALE, node.longitude
134 # try to upload with commands other than create, modify, or delete
135 def test_upload_unknown_action
136 changeset = create(:changeset)
141 <node id='1' lon='1' lat='1' changeset='#{changeset.id}' />
146 auth_header = bearer_authorization_header changeset.user
148 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
150 assert_response :bad_request
151 assert_equal "Unknown action ping, choices are create, modify, delete", @response.body
153 assert_no_changes_in changeset
157 # test for issues in https://github.com/openstreetmap/trac-tickets/issues/1568
158 def test_upload_empty_changeset
159 changeset = create(:changeset)
161 auth_header = bearer_authorization_header changeset.user
164 "<osmChange></osmChange>",
165 "<osmChange><modify/></osmChange>",
166 "<osmChange><modify></modify></osmChange>"].each do |diff|
167 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
169 assert_response :success
172 assert_no_changes_in changeset
176 # test that the X-Error-Format header works to request XML errors
177 def test_upload_xml_errors
178 changeset = create(:changeset)
180 create(:relation_member, :member => node)
182 # try and delete a node that is in use
183 diff = XML::Document.new
184 diff.root = XML::Node.new "osmChange"
185 delete = XML::Node.new "delete"
187 delete << xml_node_for_node(node)
189 auth_header = bearer_authorization_header changeset.user
190 error_header = error_format_header "xml"
192 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header.merge(error_header)
194 assert_response :success
196 assert_dom "osmError[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1
197 assert_dom "osmError>status", 1
198 assert_dom "osmError>message", 1
201 # -------------------------------------
202 # Test creating elements.
203 # -------------------------------------
205 def test_upload_create_node
207 changeset = create(:changeset, :user => user)
212 <node id='-1' lon='30' lat='60' changeset='#{changeset.id}'>
213 <tag k='amenity' v='bar'/>
214 <tag k='name' v='Foo'/>
220 auth_header = bearer_authorization_header user
222 assert_difference "Node.count" => 1,
223 "OldNode.count" => 1,
224 "NodeTag.count" => 2,
225 "OldNodeTag.count" => 2 do
226 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
228 assert_response :success
232 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
233 assert_dom "> node", 1 do |(node_el)|
234 node = Node.find(node_el["new_id"].to_i)
235 assert_dom "> @old_id", "-1"
236 assert_dom "> @new_version", "1"
241 assert_equal 1, changeset.num_changes
242 assert_predicate changeset, :num_type_changes_in_sync?
243 assert_equal 1, changeset.num_created_nodes
245 assert_equal 1, node.version
246 assert_equal changeset, node.changeset
247 assert_predicate node, :visible?
248 assert_equal({ "name" => "Foo", "amenity" => "bar" }, node.tags)
249 assert_equal 60, node.lat
250 assert_equal 30, node.lon
253 def test_upload_create_way
254 node1 = create(:node)
255 node2 = create(:node)
257 changeset = create(:changeset, :user => user)
262 <way id='-1' changeset='#{changeset.id}'>
263 <tag k='highway' v='primary'/>
264 <tag k='name' v='Foo'/>
265 <nd ref='#{node1.id}'/>
266 <nd ref='#{node2.id}'/>
272 auth_header = bearer_authorization_header user
274 assert_difference "Way.count" => 1,
277 "OldWayTag.count" => 2,
278 "WayNode.count" => 2,
279 "OldWayNode.count" => 2 do
280 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
282 assert_response :success
286 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
287 assert_dom "> way", 1 do |(way_el)|
288 way = Way.find(way_el["new_id"].to_i)
289 assert_dom "> @old_id", "-1"
290 assert_dom "> @new_version", "1"
295 assert_equal 1, changeset.num_changes
296 assert_predicate changeset, :num_type_changes_in_sync?
297 assert_equal 1, changeset.num_created_ways
299 assert_equal 1, way.version
300 assert_equal changeset, way.changeset
301 assert_predicate way, :visible?
302 assert_equal({ "name" => "Foo", "highway" => "primary" }, way.tags)
303 assert_equal [node1, node2], way.nodes
306 def test_upload_create_relation
307 node1 = create(:node)
308 way1 = create(:way_with_nodes)
309 relation1 = create(:relation)
311 changeset = create(:changeset, :user => user)
316 <relation id='-1' changeset='#{changeset.id}'>
317 <member type='node' role='n_role' ref='#{node1.id}'/>
318 <member type='way' role='w_role' ref='#{way1.id}'/>
319 <member type='relation' role='r_role' ref='#{relation1.id}'/>
320 <tag k='type' v='collection'/>
326 auth_header = bearer_authorization_header user
328 assert_difference "Relation.count" => 1,
329 "OldRelation.count" => 1,
330 "RelationTag.count" => 1,
331 "OldRelationTag.count" => 1,
332 "RelationMember.count" => 3,
333 "OldRelationMember.count" => 3 do
334 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
336 assert_response :success
340 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
341 assert_dom "> relation", 1 do |(relation_el)|
342 relation = Relation.find(relation_el["new_id"].to_i)
343 assert_dom "> @old_id", "-1"
344 assert_dom "> @new_version", "1"
349 assert_equal 1, changeset.num_changes
350 assert_predicate changeset, :num_type_changes_in_sync?
351 assert_equal 1, changeset.num_created_relations
353 assert_equal 1, relation.version
354 assert_equal changeset, relation.changeset
355 assert_predicate relation, :visible?
356 assert_equal({ "type" => "collection" }, relation.tags)
357 assert_equal [["Node", node1.id, "n_role"],
358 ["Way", way1.id, "w_role"],
359 ["Relation", relation1.id, "r_role"]], relation.members
362 def test_upload_create_elements
364 changeset = create(:changeset, :user => user)
366 way = create(:way_with_nodes, :nodes_count => 2)
367 relation = create(:relation)
372 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
373 <tag k='foo' v='bar'/>
374 <tag k='baz' v='bat'/>
376 <way id='-1' changeset='#{changeset.id}'>
377 <nd ref='#{node.id}'/>
381 <relation id='-1' changeset='#{changeset.id}'>
382 <member type='way' role='some' ref='#{way.id}'/>
383 <member type='node' role='some' ref='#{node.id}'/>
384 <member type='relation' role='some' ref='#{relation.id}'/>
390 auth_header = bearer_authorization_header user
392 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
394 assert_response :success
396 new_node_id, new_way_id, new_rel_id = nil
397 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
398 # inspect the response to find out what the new element IDs are
399 # check the old IDs are all present and negative one
400 # check the versions are present and equal one
401 assert_dom "> node", 1 do |(node_el)|
402 new_node_id = node_el["new_id"].to_i
403 assert_dom "> @old_id", "-1"
404 assert_dom "> @new_version", "1"
406 assert_dom "> way", 1 do |(way_el)|
407 new_way_id = way_el["new_id"].to_i
408 assert_dom "> @old_id", "-1"
409 assert_dom "> @new_version", "1"
411 assert_dom "> relation", 1 do |(rel_el)|
412 new_rel_id = rel_el["new_id"].to_i
413 assert_dom "> @old_id", "-1"
414 assert_dom "> @new_version", "1"
419 assert_equal 3, changeset.num_changes
420 assert_predicate changeset, :num_type_changes_in_sync?
421 assert_equal 1, changeset.num_created_nodes
422 assert_equal 1, changeset.num_created_ways
423 assert_equal 1, changeset.num_created_relations
425 assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
426 assert_equal 0, Way.find(new_way_id).tags.size, "new way should have no tags"
427 assert_equal 0, Relation.find(new_rel_id).tags.size, "new relation should have no tags"
431 # upload an element with a really long tag value
432 def test_upload_create_node_with_tag_too_long
433 changeset = create(:changeset)
438 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
439 <tag k='foo' v='#{'x' * 256}'/>
445 auth_header = bearer_authorization_header changeset.user
447 assert_no_difference "Node.count" do
448 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
450 assert_response :bad_request
453 assert_no_changes_in changeset
456 def test_upload_create_nodes_with_invalid_placeholder_reuse_in_one_action_block
457 changeset = create(:changeset)
462 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}' version='1'/>
463 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
468 auth_header = bearer_authorization_header changeset.user
470 assert_no_difference "Node.count" do
471 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
473 assert_response :bad_request
476 assert_no_changes_in changeset
479 def test_upload_create_nodes_with_invalid_placeholder_reuse_in_two_action_blocks
480 changeset = create(:changeset)
485 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}' version='1'/>
488 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
493 auth_header = bearer_authorization_header changeset.user
495 assert_no_difference "Node.count" do
496 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
498 assert_response :bad_request
501 assert_no_changes_in changeset
504 def test_upload_create_way_referring_node_placeholder_defined_later
505 changeset = create(:changeset)
510 <way id="-1" changeset="#{changeset.id}">
513 <node id="-1" lat="1" lon="2" changeset="#{changeset.id}"/>
518 auth_header = bearer_authorization_header changeset.user
520 assert_no_difference "Node.count" do
521 assert_no_difference "Way.count" do
522 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
524 assert_response :bad_request
527 assert_equal "Placeholder node not found for reference -1 in way -1", @response.body
529 assert_no_changes_in changeset
532 def test_upload_create_way_referring_undefined_node_placeholder
533 changeset = create(:changeset)
538 <way id="-1" changeset="#{changeset.id}">
545 auth_header = bearer_authorization_header changeset.user
547 assert_no_difference "Way.count" do
548 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
550 assert_response :bad_request
552 assert_equal "Placeholder node not found for reference -1 in way -1", @response.body
554 assert_no_changes_in changeset
557 def test_upload_create_existing_way_referring_undefined_node_placeholder
558 changeset = create(:changeset)
564 <way id="#{way.id}" changeset="#{changeset.id}" version="1">
571 auth_header = bearer_authorization_header changeset.user
573 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
575 assert_response :bad_request
576 assert_equal "Placeholder node not found for reference -1 in way #{way.id}", @response.body
578 assert_no_changes_in changeset
581 assert_equal 1, way.version
584 def test_upload_create_relation_referring_undefined_node_placeholder
585 changeset = create(:changeset)
590 <relation id="-1" changeset="#{changeset.id}" version="1">
591 <member type="node" role="foo" ref="-1"/>
597 auth_header = bearer_authorization_header changeset.user
599 assert_no_difference "Relation.count" do
600 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
602 assert_response :bad_request
604 assert_equal "Placeholder Node not found for reference -1 in relation -1.", @response.body
606 assert_no_changes_in changeset
609 def test_upload_create_existing_relation_referring_undefined_way_placeholder
610 changeset = create(:changeset)
611 relation = create(:relation)
616 <relation id="#{relation.id}" changeset="#{changeset.id}" version="1">
617 <member type="way" role="bar" ref="-1"/>
623 auth_header = bearer_authorization_header changeset.user
625 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
627 assert_response :bad_request
628 assert_equal "Placeholder Way not found for reference -1 in relation #{relation.id}.", @response.body
630 assert_no_changes_in changeset
633 assert_equal 1, relation.version
636 def test_upload_create_relations_with_circular_references
637 changeset = create(:changeset)
640 <osmChange version='0.6'>
642 <relation id='-2' version='0' changeset='#{changeset.id}'>
643 <member type='relation' role='' ref='-4' />
644 <tag k='type' v='route' />
645 <tag k='name' v='AtoB' />
647 <relation id='-3' version='0' changeset='#{changeset.id}'>
648 <tag k='type' v='route' />
649 <tag k='name' v='BtoA' />
651 <relation id='-4' version='0' changeset='#{changeset.id}'>
652 <member type='relation' role='' ref='-2' />
653 <member type='relation' role='' ref='-3' />
654 <tag k='type' v='route_master' />
655 <tag k='name' v='master' />
661 auth_header = bearer_authorization_header changeset.user
663 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
665 assert_response :bad_request
666 assert_equal "Placeholder Relation not found for reference -4 in relation -2.", @response.body
668 assert_no_changes_in changeset
671 # -------------------------------------
672 # Test modifying elements.
673 # -------------------------------------
675 def test_upload_modify_node
677 changeset = create(:changeset, :user => user)
678 node = create(:node, :latitude => 0, :longitude => 0)
679 create(:node_tag, :node => node)
684 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
689 auth_header = bearer_authorization_header user
691 assert_difference "Node.count" => 0,
692 "OldNode.count" => 1,
693 "NodeTag.count" => -1,
694 "OldNodeTag.count" => 0 do
695 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
697 assert_response :success
700 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
701 assert_dom "> node", 1 do
702 assert_dom "> @old_id", node.id.to_s
703 assert_dom "> @new_id", node.id.to_s
704 assert_dom "> @new_version", "2"
709 assert_equal 1, changeset.num_changes
710 assert_predicate changeset, :num_type_changes_in_sync?
711 assert_equal 1, changeset.num_modified_nodes
714 assert_equal 2, node.version
715 assert_equal 2 * GeoRecord::SCALE, node.latitude
716 assert_equal 1 * GeoRecord::SCALE, node.longitude
717 assert_equal 0, node.tags.size, "node #{node.id} should now have no tags"
720 def test_upload_modify_way
722 changeset = create(:changeset, :user => user)
724 way = create(:way_with_nodes, :nodes_count => 3)
725 create(:way_tag, :way => way)
730 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
731 <nd ref='#{node.id}'/>
737 auth_header = bearer_authorization_header user
739 assert_difference "Way.count" => 0,
741 "WayTag.count" => -1,
742 "OldWayTag.count" => 0,
743 "WayNode.count" => -2,
744 "OldWayNode.count" => 1 do
745 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
747 assert_response :success
750 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
751 assert_dom "> way", 1 do
752 assert_dom "> @old_id", way.id.to_s
753 assert_dom "> @new_id", way.id.to_s
754 assert_dom "> @new_version", "2"
759 assert_equal 1, changeset.num_changes
760 assert_predicate changeset, :num_type_changes_in_sync?
761 assert_equal 1, changeset.num_modified_ways
764 assert_equal 2, way.version
765 assert_equal 0, way.tags.size, "way #{way.id} should now have no tags"
766 assert_equal [node], way.nodes
769 def test_upload_modify_relation
771 changeset = create(:changeset, :user => user)
773 way = create(:way_with_nodes)
774 relation = create(:relation)
775 other_relation = create(:relation)
776 create(:relation_tag, :relation => relation)
781 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'>
782 <member type='way' role='some' ref='#{way.id}'/>
783 <member type='node' role='some' ref='#{node.id}'/>
784 <member type='relation' role='some' ref='#{other_relation.id}'/>
790 auth_header = bearer_authorization_header user
792 assert_difference "Relation.count" => 0,
793 "OldRelation.count" => 1,
794 "RelationTag.count" => -1,
795 "OldRelationTag.count" => 0,
796 "RelationMember.count" => 3,
797 "OldRelationMember.count" => 3 do
798 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
800 assert_response :success
803 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
804 assert_dom "> relation", 1 do
805 assert_dom "> @old_id", relation.id.to_s
806 assert_dom "> @new_id", relation.id.to_s
807 assert_dom "> @new_version", "2"
812 assert_equal 1, changeset.num_changes
813 assert_predicate changeset, :num_type_changes_in_sync?
814 assert_equal 1, changeset.num_modified_relations
817 assert_equal 2, relation.version
818 assert_equal 0, relation.tags.size, "relation #{relation.id} should now have no tags"
819 assert_equal [["Way", way.id, "some"], ["Node", node.id, "some"], ["Relation", other_relation.id, "some"]], relation.members
822 def test_upload_modify_elements
824 changeset = create(:changeset, :user => user)
825 node = create(:node, :latitude => 0, :longitude => 0)
827 relation = create(:relation)
828 other_relation = create(:relation)
830 # create some tags, since we test that they are removed later
831 create(:node_tag, :node => node)
832 create(:way_tag, :way => way)
833 create(:relation_tag, :relation => relation)
835 # simple diff to change a node, way and relation by removing their tags
839 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
840 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
841 <nd ref='#{node.id}'/>
845 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'>
846 <member type='way' role='some' ref='#{way.id}'/>
847 <member type='node' role='some' ref='#{node.id}'/>
848 <member type='relation' role='some' ref='#{other_relation.id}'/>
854 auth_header = bearer_authorization_header user
856 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
858 assert_response :success
860 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
861 assert_dom "> node", 1 do
862 assert_dom "> @old_id", node.id.to_s
863 assert_dom "> @new_id", node.id.to_s
864 assert_dom "> @new_version", "2"
866 assert_dom "> way", 1 do
867 assert_dom "> @old_id", way.id.to_s
868 assert_dom "> @new_id", way.id.to_s
869 assert_dom "> @new_version", "2"
871 assert_dom "> relation", 1 do
872 assert_dom "> @old_id", relation.id.to_s
873 assert_dom "> @new_id", relation.id.to_s
874 assert_dom "> @new_version", "2"
879 assert_equal 3, changeset.num_changes
880 assert_predicate changeset, :num_type_changes_in_sync?
881 assert_equal 1, changeset.num_modified_nodes
882 assert_equal 1, changeset.num_modified_ways
883 assert_equal 1, changeset.num_modified_relations
886 assert_equal 2, node.version
887 assert_equal 2 * GeoRecord::SCALE, node.latitude
888 assert_equal 1 * GeoRecord::SCALE, node.longitude
889 assert_equal 0, node.tags.size, "node #{node.id} should now have no tags"
891 assert_equal 2, way.version
892 assert_equal 0, way.tags.size, "way #{way.id} should now have no tags"
893 assert_equal [node], way.nodes
895 assert_equal 2, relation.version
896 assert_equal 0, relation.tags.size, "relation #{relation.id} should now have no tags"
897 assert_equal [["Way", way.id, "some"], ["Node", node.id, "some"], ["Relation", other_relation.id, "some"]], relation.members
901 # upload multiple versions of the same element in the same diff.
902 def test_upload_modify_multiple_node_versions
904 changeset = create(:changeset)
906 # change the location of a node multiple times, each time referencing
907 # the last version. doesn't this depend on version numbers being
912 <node id='#{node.id}' lon='0.0' lat='0.0' changeset='#{changeset.id}' version='1'/>
913 <node id='#{node.id}' lon='0.1' lat='0.0' changeset='#{changeset.id}' version='2'/>
914 <node id='#{node.id}' lon='0.1' lat='0.1' changeset='#{changeset.id}' version='3'/>
915 <node id='#{node.id}' lon='0.1' lat='0.2' changeset='#{changeset.id}' version='4'/>
916 <node id='#{node.id}' lon='0.2' lat='0.2' changeset='#{changeset.id}' version='5'/>
917 <node id='#{node.id}' lon='0.3' lat='0.2' changeset='#{changeset.id}' version='6'/>
918 <node id='#{node.id}' lon='0.3' lat='0.3' changeset='#{changeset.id}' version='7'/>
919 <node id='#{node.id}' lon='0.9' lat='0.9' changeset='#{changeset.id}' version='8'/>
924 auth_header = bearer_authorization_header changeset.user
926 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
928 assert_response :success
930 assert_dom "diffResult>node", 8
933 assert_equal 8, changeset.num_changes
934 assert_predicate changeset, :num_type_changes_in_sync?
935 assert_equal 8, changeset.num_modified_nodes
938 assert_equal 9, node.version
939 assert_equal 0.9 * GeoRecord::SCALE, node.latitude
940 assert_equal 0.9 * GeoRecord::SCALE, node.longitude
944 # upload multiple versions of the same element in the same diff, but
945 # keep the version numbers the same.
946 def test_upload_modify_duplicate_node_versions
947 node = create(:node, :latitude => 0, :longitude => 0)
948 changeset = create(:changeset)
953 <node id='#{node.id}' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
954 <node id='#{node.id}' lon='2' lat='2' changeset='#{changeset.id}' version='1'/>
959 auth_header = bearer_authorization_header changeset.user
961 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
963 assert_response :conflict
965 assert_no_changes_in changeset
968 assert_equal 1, node.version
969 assert_equal 0, node.latitude
970 assert_equal 0, node.longitude
974 # try to upload some elements without specifying the version
975 def test_upload_modify_missing_node_version
976 node = create(:node, :latitude => 0, :longitude => 0)
977 changeset = create(:changeset)
982 <node id='#{node.id}' lon='1' lat='1' changeset='#{changeset.id}'/>
987 auth_header = bearer_authorization_header changeset.user
989 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
991 assert_response :bad_request
993 assert_no_changes_in changeset
996 assert_equal 1, node.version
997 assert_equal 0, node.latitude
998 assert_equal 0, node.longitude
1002 # create a diff which references several changesets, which should cause
1003 # a rollback and none of the diff gets committed
1004 def test_upload_modify_with_references_to_different_changesets
1005 changeset1 = create(:changeset)
1006 changeset2 = create(:changeset, :user => changeset1.user)
1007 node1 = create(:node)
1008 node2 = create(:node)
1010 # simple diff to create a node way and relation using placeholders
1014 <node id='#{node1.id}' lon='0' lat='0' changeset='#{changeset1.id}' version='1'/>
1017 <node id='#{node2.id}' lon='0' lat='0' changeset='#{changeset2.id}' version='1'/>
1022 auth_header = bearer_authorization_header changeset1.user
1024 post api_changeset_upload_path(changeset1), :params => diff, :headers => auth_header
1026 assert_response :conflict
1028 assert_no_changes_in changeset1
1029 assert_no_changes_in changeset2
1031 assert_nodes_are_equal(node1, Node.find(node1.id))
1032 assert_nodes_are_equal(node2, Node.find(node2.id))
1036 # upload a valid changeset which has a mixture of whitespace
1037 # to check a bug https://github.com/openstreetmap/trac-tickets/issues/1565
1038 def test_upload_modify_with_mixed_whitespace
1039 changeset = create(:changeset)
1040 node = create(:node)
1041 way = create(:way_with_nodes, :nodes_count => 2)
1042 relation = create(:relation)
1043 other_relation = create(:relation)
1044 create(:relation_tag, :relation => relation)
1048 <modify><node id='#{node.id}' lon='0' lat='0' changeset='#{changeset.id}'
1050 <node id='#{node.id}' lon='1' lat='1' changeset='#{changeset.id}' version='2'><tag k='k' v='v'/></node></modify>
1052 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'><member
1053 type='way' role='some' ref='#{way.id}'/><member
1054 type='node' role='some' ref='#{node.id}'/>
1055 <member type='relation' role='some' ref='#{other_relation.id}'/>
1057 </modify></osmChange>
1060 auth_header = bearer_authorization_header changeset.user
1062 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1064 assert_response :success
1066 assert_dom "diffResult>node", 2
1067 assert_dom "diffResult>relation", 1
1070 assert_equal 3, changeset.num_changes
1071 assert_predicate changeset, :num_type_changes_in_sync?
1072 assert_equal 2, changeset.num_modified_nodes
1073 assert_equal 1, changeset.num_modified_relations
1075 assert_equal 1, Node.find(node.id).tags.size, "node #{node.id} should now have one tag"
1076 assert_equal 0, Relation.find(relation.id).tags.size, "relation #{relation.id} should now have no tags"
1079 def test_upload_modify_unknown_node_placeholder
1080 check_upload_results_in_not_found do |changeset|
1081 "<modify><node id='-1' lon='0' lat='0' changeset='#{changeset.id}' version='1'/></modify>"
1085 def test_upload_modify_unknown_way_placeholder
1086 check_upload_results_in_not_found do |changeset|
1087 "<modify><way id='-1' changeset='#{changeset.id}' version='1'/></modify>"
1091 def test_upload_modify_unknown_relation_placeholder
1092 check_upload_results_in_not_found do |changeset|
1093 "<modify><relation id='-1' changeset='#{changeset.id}' version='1'/></modify>"
1097 # -------------------------------------
1098 # Test deleting elements.
1099 # -------------------------------------
1101 def test_upload_delete_node
1102 changeset = create(:changeset)
1103 node = create(:node, :lat => 0, :lon => 0)
1104 create(:node_tag, :node => node)
1109 <node id='#{node.id}' changeset='#{changeset.id}' version='1' lat='0' lon='0'/>
1114 auth_header = bearer_authorization_header changeset.user
1116 assert_difference "Node.count" => 0,
1117 "OldNode.count" => 1,
1118 "NodeTag.count" => -1,
1119 "OldNodeTag.count" => 0 do
1120 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1122 assert_response :success
1125 assert_dom "diffResult", 1 do
1126 assert_dom "> node", 1 do
1127 assert_dom "> @old_id", node.id.to_s
1132 assert_equal 1, changeset.num_changes
1133 assert_predicate changeset, :num_type_changes_in_sync?
1134 assert_equal 1, changeset.num_deleted_nodes
1137 assert_not_predicate node, :visible?
1140 def test_upload_delete_way
1141 changeset = create(:changeset)
1142 way = create(:way_with_nodes, :nodes_count => 3)
1143 create(:way_tag, :way => way)
1148 <way id='#{way.id}' changeset='#{changeset.id}' version='1'/>
1153 auth_header = bearer_authorization_header changeset.user
1155 assert_difference "Way.count" => 0,
1156 "OldWay.count" => 1,
1157 "WayTag.count" => -1,
1158 "OldWayTag.count" => 0,
1159 "WayNode.count" => -3,
1160 "OldWayNode.count" => 0 do
1161 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1163 assert_response :success
1166 assert_dom "diffResult", 1 do
1167 assert_dom "> way", 1 do
1168 assert_dom "> @old_id", way.id.to_s
1173 assert_equal 1, changeset.num_changes
1174 assert_predicate changeset, :num_type_changes_in_sync?
1175 assert_equal 1, changeset.num_deleted_ways
1178 assert_not_predicate way, :visible?
1181 def test_upload_delete_relation
1182 changeset = create(:changeset)
1183 relation = create(:relation)
1184 create(:relation_member, :relation => relation, :member => create(:node))
1185 create(:relation_tag, :relation => relation)
1190 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'/>
1195 auth_header = bearer_authorization_header changeset.user
1197 assert_difference "Relation.count" => 0,
1198 "OldRelation.count" => 1,
1199 "RelationTag.count" => -1,
1200 "OldRelationTag.count" => 0,
1201 "RelationMember.count" => -1,
1202 "OldRelationMember.count" => 0 do
1203 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1205 assert_response :success
1208 assert_dom "diffResult", 1 do
1209 assert_dom "> relation", 1 do
1210 assert_dom "> @old_id", relation.id.to_s
1215 assert_equal 1, changeset.num_changes
1216 assert_predicate changeset, :num_type_changes_in_sync?
1217 assert_equal 1, changeset.num_deleted_relations
1220 assert_not_predicate relation, :visible?
1224 # test a complex delete where we delete elements which rely on each other
1225 # in the same transaction.
1226 def test_upload_delete_elements
1227 changeset = create(:changeset)
1228 super_relation = create(:relation)
1229 used_relation = create(:relation)
1230 used_way = create(:way)
1231 used_node = create(:node)
1232 create(:relation_member, :relation => super_relation, :member => used_relation)
1233 create(:relation_member, :relation => super_relation, :member => used_way)
1234 create(:relation_member, :relation => super_relation, :member => used_node)
1236 diff = XML::Document.new
1237 diff.root = XML::Node.new "osmChange"
1238 delete = XML::Node.new "delete"
1240 delete << xml_node_for_relation(super_relation)
1241 delete << xml_node_for_relation(used_relation)
1242 delete << xml_node_for_way(used_way)
1243 delete << xml_node_for_node(used_node)
1244 %w[node way relation].each do |type|
1245 delete.find("//osmChange/delete/#{type}").each do |n|
1246 n["changeset"] = changeset.id.to_s
1250 auth_header = bearer_authorization_header changeset.user
1252 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1254 assert_response :success
1256 assert_dom "diffResult", 1 do
1257 assert_dom "> node", 1
1258 assert_dom "> way", 1
1259 assert_dom "> relation", 2
1263 assert_equal 4, changeset.num_changes
1264 assert_predicate changeset, :num_type_changes_in_sync?
1265 assert_equal 1, changeset.num_deleted_nodes
1266 assert_equal 1, changeset.num_deleted_ways
1267 assert_equal 2, changeset.num_deleted_relations
1269 assert_not Node.find(used_node.id).visible
1270 assert_not Way.find(used_way.id).visible
1271 assert_not Relation.find(super_relation.id).visible
1272 assert_not Relation.find(used_relation.id).visible
1276 # test uploading a delete with no lat/lon, as they are optional in the osmChange spec.
1277 def test_upload_delete_node_without_latlon
1278 node = create(:node)
1279 changeset = create(:changeset)
1281 diff = "<osmChange><delete><node id='#{node.id}' version='#{node.version}' changeset='#{changeset.id}'/></delete></osmChange>"
1283 auth_header = bearer_authorization_header changeset.user
1285 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1287 assert_response :success
1289 assert_dom "diffResult", 1 do
1290 assert_dom "> node", 1 do
1291 assert_dom "> @old_id", node.id.to_s
1292 assert_dom "> @new_id", 0
1293 assert_dom "> @new_version", 0
1298 assert_equal 1, changeset.num_changes
1299 assert_predicate changeset, :num_type_changes_in_sync?
1300 assert_equal 1, changeset.num_deleted_nodes
1303 assert_not node.visible
1307 # test that deleting stuff in a transaction doesn't bypass the checks
1308 # to ensure that used elements are not deleted.
1309 def test_upload_delete_referenced_elements
1310 changeset = create(:changeset)
1311 relation = create(:relation)
1312 other_relation = create(:relation)
1313 used_way = create(:way)
1314 used_node = create(:node)
1315 create(:relation_member, :relation => relation, :member => used_way)
1316 create(:relation_member, :relation => relation, :member => used_node)
1318 diff = XML::Document.new
1319 diff.root = XML::Node.new "osmChange"
1320 delete = XML::Node.new "delete"
1322 delete << xml_node_for_relation(other_relation)
1323 delete << xml_node_for_way(used_way)
1324 delete << xml_node_for_node(used_node)
1325 %w[node way relation].each do |type|
1326 delete.find("//osmChange/delete/#{type}").each do |n|
1327 n["changeset"] = changeset.id.to_s
1331 auth_header = bearer_authorization_header changeset.user
1333 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1335 assert_response :precondition_failed
1336 assert_equal "Precondition failed: Way #{used_way.id} is still used by relations #{relation.id}.", @response.body
1338 assert_no_changes_in changeset
1340 assert Node.find(used_node.id).visible
1341 assert Way.find(used_way.id).visible
1342 assert Relation.find(relation.id).visible
1343 assert Relation.find(other_relation.id).visible
1347 # test that a conditional delete of an in use object works.
1348 def test_upload_delete_if_unused
1349 changeset = create(:changeset)
1350 super_relation = create(:relation)
1351 used_relation = create(:relation)
1352 used_way = create(:way)
1353 used_node = create(:node)
1354 create(:relation_member, :relation => super_relation, :member => used_relation)
1355 create(:relation_member, :relation => super_relation, :member => used_way)
1356 create(:relation_member, :relation => super_relation, :member => used_node)
1358 diff = XML::Document.new
1359 diff.root = XML::Node.new "osmChange"
1360 delete = XML::Node.new "delete"
1362 delete["if-unused"] = ""
1363 delete << xml_node_for_relation(used_relation)
1364 delete << xml_node_for_way(used_way)
1365 delete << xml_node_for_node(used_node)
1366 %w[node way relation].each do |type|
1367 delete.find("//osmChange/delete/#{type}").each do |n|
1368 n["changeset"] = changeset.id.to_s
1372 auth_header = bearer_authorization_header changeset.user
1374 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1376 assert_response :success
1378 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
1379 assert_dom "> node", 1 do
1380 assert_dom "> @old_id", used_node.id.to_s
1381 assert_dom "> @new_id", used_node.id.to_s
1382 assert_dom "> @new_version", used_node.version.to_s
1384 assert_dom "> way", 1 do
1385 assert_dom "> @old_id", used_way.id.to_s
1386 assert_dom "> @new_id", used_way.id.to_s
1387 assert_dom "> @new_version", used_way.version.to_s
1389 assert_dom "> relation", 1 do
1390 assert_dom "> @old_id", used_relation.id.to_s
1391 assert_dom "> @new_id", used_relation.id.to_s
1392 assert_dom "> @new_version", used_relation.version.to_s
1396 assert_no_changes_in changeset
1398 assert Node.find(used_node.id).visible
1399 assert Way.find(used_way.id).visible
1400 assert Relation.find(used_relation.id).visible
1403 def test_upload_delete_with_multiple_blocks_and_if_unused
1404 changeset = create(:changeset)
1405 node = create(:node)
1407 create(:way_node, :way => way, :node => node)
1408 alone_node = create(:node)
1411 <osmChange version='0.6'>
1412 <delete version="0.6">
1413 <node id="#{node.id}" version="#{node.version}" changeset="#{changeset.id}"/>
1415 <delete version="0.6" if-unused="true">
1416 <node id="#{alone_node.id}" version="#{alone_node.version}" changeset="#{changeset.id}"/>
1421 auth_header = bearer_authorization_header changeset.user
1423 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1425 assert_response :precondition_failed
1426 assert_equal "Precondition failed: Node #{node.id} is still used by ways #{way.id}.", @response.body
1428 assert_no_changes_in changeset
1431 def test_upload_delete_unknown_node_placeholder
1432 check_upload_results_in_not_found do |changeset|
1433 "<delete><node id='-1' changeset='#{changeset.id}' version='1'/></delete>"
1437 def test_upload_delete_unknown_way_placeholder
1438 check_upload_results_in_not_found do |changeset|
1439 "<delete><way id='-1' changeset='#{changeset.id}' version='1'/></delete>"
1443 def test_upload_delete_unknown_relation_placeholder
1444 check_upload_results_in_not_found do |changeset|
1445 "<delete><relation id='-1' changeset='#{changeset.id}' version='1'/></delete>"
1449 # -------------------------------------
1450 # Test combined element changes.
1451 # -------------------------------------
1454 # upload something which creates new objects and inserts them into
1455 # existing containers using placeholders.
1456 def test_upload_create_and_insert_elements
1458 node = create(:node)
1459 relation = create(:relation)
1460 create(:way_node, :way => way, :node => node)
1461 changeset = create(:changeset)
1466 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1467 <tag k='foo' v='bar'/>
1468 <tag k='baz' v='bat'/>
1472 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
1474 <nd ref='#{node.id}'/>
1476 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'>
1477 <member type='way' role='some' ref='#{way.id}'/>
1478 <member type='node' role='some' ref='-1'/>
1479 <member type='relation' role='some' ref='#{relation.id}'/>
1485 auth_header = bearer_authorization_header changeset.user
1487 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1489 assert_response :success
1492 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
1493 assert_dom "> node", 1 do |(node_el)|
1494 new_node_id = node_el["new_id"].to_i
1496 assert_dom "> way", 1
1497 assert_dom "> relation", 1
1501 assert_equal 3, changeset.num_changes
1502 assert_predicate changeset, :num_type_changes_in_sync?
1503 assert_equal 1, changeset.num_created_nodes
1504 assert_equal 1, changeset.num_modified_ways
1505 assert_equal 1, changeset.num_modified_relations
1507 assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
1508 assert_equal [new_node_id, node.id], Way.find(way.id).nds, "way nodes should match"
1509 Relation.find(relation.id).members.each do |type, id, _role|
1510 assert_equal new_node_id, id, "relation should contain new node" if type == "node"
1515 # test that a placeholder can be reused within the same upload.
1516 def test_upload_create_modify_delete_node_reusing_placeholder
1517 changeset = create(:changeset)
1522 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1523 <tag k="foo" v="bar"/>
1527 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
1530 <node id='-1' lon='2' lat='2' changeset='#{changeset.id}' version='2'/>
1535 auth_header = bearer_authorization_header changeset.user
1537 assert_difference "Node.count", 1 do
1538 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1540 assert_response :success
1543 assert_dom "diffResult>node", 3
1544 assert_dom "diffResult>node[old_id='-1']", 3
1547 assert_equal 3, changeset.num_changes
1548 assert_predicate changeset, :num_type_changes_in_sync?
1549 assert_equal 1, changeset.num_created_nodes
1550 assert_equal 1, changeset.num_modified_nodes
1551 assert_equal 1, changeset.num_deleted_nodes
1554 assert_equal 3, node.version
1555 assert_not node.visible
1558 def test_upload_create_and_duplicate_delete
1559 changeset = create(:changeset)
1564 <node id="-1" lat="39" lon="116" changeset="#{changeset.id}" />
1567 <node id="-1" version="1" changeset="#{changeset.id}" />
1568 <node id="-1" version="1" changeset="#{changeset.id}" />
1573 auth_header = bearer_authorization_header changeset.user
1575 assert_no_difference "Node.count" do
1576 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1578 assert_response :gone
1581 assert_no_changes_in changeset
1584 def test_upload_create_and_duplicate_delete_if_unused
1585 changeset = create(:changeset)
1590 <node id="-1" lat="39" lon="116" changeset="#{changeset.id}" />
1592 <delete if-unused="true">
1593 <node id="-1" version="1" changeset="#{changeset.id}" />
1594 <node id="-1" version="1" changeset="#{changeset.id}" />
1599 auth_header = bearer_authorization_header changeset.user
1601 assert_difference "Node.count", 1 do
1602 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1604 assert_response :success
1607 assert_dom "diffResult>node", 3
1608 assert_dom "diffResult>node[old_id='-1']", 3
1609 assert_dom "diffResult>node[new_version='1']", 1
1610 assert_dom "diffResult>node[new_version='2']", 1
1613 assert_equal 2, changeset.num_changes
1614 assert_predicate changeset, :num_type_changes_in_sync?
1615 assert_equal 1, changeset.num_created_nodes
1616 assert_equal 1, changeset.num_deleted_nodes
1619 assert_equal 2, node.version
1620 assert_not node.visible
1623 # -------------------------------------
1624 # Test bounding boxes.
1625 # -------------------------------------
1627 def test_upload_bbox_of_widely_spaced_nodes
1628 user = create(:user)
1630 # create an old changeset to ensure we have the maximum rate limit
1631 create(:changeset, :user => user, :created_at => Time.now.utc - 28.days)
1633 changeset = create(:changeset, :user => user)
1635 # upload some widely-spaced nodes, spiralling positive and negative
1639 <node id='-1' lon='-20' lat='-10' changeset='#{changeset.id}'/>
1640 <node id='-10' lon='20' lat='10' changeset='#{changeset.id}'/>
1641 <node id='-2' lon='-40' lat='-20' changeset='#{changeset.id}'/>
1642 <node id='-11' lon='40' lat='20' changeset='#{changeset.id}'/>
1643 <node id='-3' lon='-60' lat='-30' changeset='#{changeset.id}'/>
1644 <node id='-12' lon='60' lat='30' changeset='#{changeset.id}'/>
1645 <node id='-4' lon='-80' lat='-40' changeset='#{changeset.id}'/>
1646 <node id='-13' lon='80' lat='40' changeset='#{changeset.id}'/>
1647 <node id='-5' lon='-100' lat='-50' changeset='#{changeset.id}'/>
1648 <node id='-14' lon='100' lat='50' changeset='#{changeset.id}'/>
1649 <node id='-6' lon='-120' lat='-60' changeset='#{changeset.id}'/>
1650 <node id='-15' lon='120' lat='60' changeset='#{changeset.id}'/>
1651 <node id='-7' lon='-140' lat='-70' changeset='#{changeset.id}'/>
1652 <node id='-16' lon='140' lat='70' changeset='#{changeset.id}'/>
1653 <node id='-8' lon='-160' lat='-80' changeset='#{changeset.id}'/>
1654 <node id='-17' lon='160' lat='80' changeset='#{changeset.id}'/>
1655 <node id='-9' lon='-179.9' lat='-89.9' changeset='#{changeset.id}'/>
1656 <node id='-18' lon='179.9' lat='89.9' changeset='#{changeset.id}'/>
1661 auth_header = bearer_authorization_header user
1663 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1665 assert_response :success
1668 assert_equal 18, changeset.num_changes
1669 assert_predicate changeset, :num_type_changes_in_sync?
1670 assert_equal 18, changeset.num_created_nodes
1672 # check that the changeset bbox is within bounds
1673 assert_operator changeset.min_lon, :>=, -180 * GeoRecord::SCALE, "Minimum longitude (#{changeset.min_lon / GeoRecord::SCALE}) should be >= -180 to be valid."
1674 assert_operator changeset.max_lon, :<=, 180 * GeoRecord::SCALE, "Maximum longitude (#{changeset.max_lon / GeoRecord::SCALE}) should be <= 180 to be valid."
1675 assert_operator changeset.min_lat, :>=, -90 * GeoRecord::SCALE, "Minimum latitude (#{changeset.min_lat / GeoRecord::SCALE}) should be >= -90 to be valid."
1676 assert_operator changeset.max_lat, :<=, 90 * GeoRecord::SCALE, "Maximum latitude (#{changeset.max_lat / GeoRecord::SCALE}) should be <= 90 to be valid."
1679 def test_upload_bbox_of_moved_node
1680 changeset = create(:changeset)
1681 node = create(:node, :lat => 1.0, :lon => 2.0)
1686 <node id='#{node.id}' lat='1.1' lon='2.1' changeset='#{changeset.id}' version='1'/>
1691 auth_header = bearer_authorization_header changeset.user
1693 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1695 assert_response :success
1698 assert_equal 1, changeset.num_changes
1699 assert_predicate changeset, :num_type_changes_in_sync?
1700 assert_equal 1, changeset.num_modified_nodes
1703 assert_equal 1.0 * GeoRecord::SCALE, changeset.min_lat, "min_lat should be 1.0 degrees"
1704 assert_equal 2.0 * GeoRecord::SCALE, changeset.min_lon, "min_lon should be 2.0 degrees"
1705 assert_equal 1.1 * GeoRecord::SCALE, changeset.max_lat, "max_lat should be 1.1 degrees"
1706 assert_equal 2.1 * GeoRecord::SCALE, changeset.max_lon, "max_lon should be 2.1 degrees"
1709 def test_upload_bbox_of_extended_way
1711 initial_node = create(:node, :lat => 1.1, :lon => 2.1)
1712 create(:way_node, :way => way, :node => initial_node)
1713 added_node = create(:node, :lat => 1.3, :lon => 2.3)
1714 changeset = create(:changeset)
1719 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
1720 <nd ref='#{initial_node.id}'/>
1721 <nd ref='#{added_node.id}'/>
1727 auth_header = bearer_authorization_header changeset.user
1729 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1731 assert_response :success
1734 assert_equal 1, changeset.num_changes
1735 assert_predicate changeset, :num_type_changes_in_sync?
1736 assert_equal 1, changeset.num_modified_ways
1739 assert_equal 1.1 * GeoRecord::SCALE, changeset.min_lat, "min_lat should be 1.1 degrees"
1740 assert_equal 2.1 * GeoRecord::SCALE, changeset.min_lon, "min_lon should be 2.1 degrees"
1741 assert_equal 1.3 * GeoRecord::SCALE, changeset.max_lat, "max_lat should be 1.3 degrees"
1742 assert_equal 2.3 * GeoRecord::SCALE, changeset.max_lon, "max_lon should be 2.3 degrees"
1745 # -------------------------------------
1746 # Test upload rate/size limits.
1747 # -------------------------------------
1749 def test_upload_initial_rate_limit
1750 user = create(:user)
1751 node = create(:node)
1752 way = create(:way_with_nodes, :nodes_count => 2)
1753 relation = create(:relation)
1755 # create a changeset that puts us near the initial rate limit
1756 num_changes = Settings.initial_changes_per_hour - 2
1757 changeset = create(:changeset, :user => user,
1758 :created_at => Time.now.utc - 5.minutes,
1759 :num_changes => num_changes,
1760 :num_created_nodes => num_changes)
1765 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1766 <tag k='foo' v='bar'/>
1767 <tag k='baz' v='bat'/>
1769 <way id='-1' changeset='#{changeset.id}'>
1770 <nd ref='#{node.id}'/>
1774 <relation id='-1' changeset='#{changeset.id}'>
1775 <member type='way' role='some' ref='#{way.id}'/>
1776 <member type='node' role='some' ref='#{node.id}'/>
1777 <member type='relation' role='some' ref='#{relation.id}'/>
1783 auth_header = bearer_authorization_header user
1785 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1787 assert_response :too_many_requests, "upload did not hit rate limit"
1790 assert_equal num_changes, changeset.num_changes
1791 assert_predicate changeset, :num_type_changes_in_sync?
1794 def test_upload_maximum_rate_limit
1795 user = create(:user)
1796 node = create(:node)
1797 way = create(:way_with_nodes, :nodes_count => 2)
1798 relation = create(:relation)
1800 # create a changeset to establish our initial edit time
1801 changeset = create(:changeset, :user => user,
1802 :created_at => Time.now.utc - 28.days)
1804 # create changeset to put us near the maximum rate limit
1805 remaining_num_changes = Settings.max_changes_per_hour - 2
1807 while remaining_num_changes.positive?
1808 num_changes = [remaining_num_changes, Changeset::MAX_ELEMENTS].min
1809 changeset = create(:changeset, :user => user,
1810 :created_at => Time.now.utc - 5.minutes,
1811 :num_changes => num_changes,
1812 :num_created_nodes => num_changes)
1813 remaining_num_changes -= num_changes
1819 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1820 <tag k='foo' v='bar'/>
1821 <tag k='baz' v='bat'/>
1823 <way id='-1' changeset='#{changeset.id}'>
1824 <nd ref='#{node.id}'/>
1828 <relation id='-1' changeset='#{changeset.id}'>
1829 <member type='way' role='some' ref='#{way.id}'/>
1830 <member type='node' role='some' ref='#{node.id}'/>
1831 <member type='relation' role='some' ref='#{relation.id}'/>
1837 auth_header = bearer_authorization_header user
1839 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1841 assert_response :too_many_requests, "upload did not hit rate limit"
1844 assert_equal num_changes, changeset.num_changes
1845 assert_predicate changeset, :num_type_changes_in_sync?
1848 def test_upload_initial_size_limit
1849 user = create(:user)
1851 # create a changeset that puts us near the initial size limit
1852 changeset = create(:changeset, :user => user,
1853 :min_lat => (-0.5 * GeoRecord::SCALE).round, :min_lon => (0.5 * GeoRecord::SCALE).round,
1854 :max_lat => (0.5 * GeoRecord::SCALE).round, :max_lon => (2.5 * GeoRecord::SCALE).round)
1859 <node id='-1' lon='0.9' lat='2.9' changeset='#{changeset.id}'>
1860 <tag k='foo' v='bar'/>
1861 <tag k='baz' v='bat'/>
1867 auth_header = bearer_authorization_header user
1869 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1871 assert_response :content_too_large, "upload did not hit size limit"
1873 assert_no_changes_in changeset
1876 def test_upload_size_limit_after_one_week
1877 user = create(:user)
1879 # create a changeset to establish our initial edit time
1880 create(:changeset, :user => user, :created_at => Time.now.utc - 7.days)
1882 # create a changeset that puts us near the initial size limit
1883 changeset = create(:changeset, :user => user, :bbox => [0.5, -0.5, 2.5, 0.5])
1888 <node id='-1' lon='35' lat='35' changeset='#{changeset.id}'>
1889 <tag k='foo' v='bar'/>
1890 <tag k='baz' v='bat'/>
1896 auth_header = bearer_authorization_header user
1898 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1900 assert_response :content_too_large, "upload did not hit size limit"
1902 assert_no_changes_in changeset
1907 def check_upload_results_in_not_found(&)
1908 changeset = create(:changeset)
1909 diff = "<osmChange>#{yield changeset}</osmChange>"
1910 auth_header = bearer_authorization_header changeset.user
1912 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1914 assert_response :not_found
1916 assert_no_changes_in changeset
1919 def assert_no_changes_in(changeset)
1921 assert_equal 0, changeset.num_changes
1922 assert_predicate changeset, :num_type_changes_in_sync?