5 class UploadsControllerTest < ActionDispatch::IntegrationTest
7 # test all routes which lead to this controller
10 { :path => "/api/0.6/changeset/1/upload", :method => :post },
11 { :controller => "api/changesets/uploads", :action => "create", :changeset_id => "1" }
15 def test_upload_when_unauthorized
16 changeset = create(:changeset)
17 node = create(:node, :latitude => 0, :longitude => 0)
22 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
27 post api_changeset_upload_path(changeset), :params => diff
29 assert_response :unauthorized
31 assert_no_changes_in changeset
34 assert_equal 1, node.version
35 assert_equal 0, node.latitude
36 assert_equal 0, node.longitude
39 def test_upload_by_private_user
40 user = create(:user, :data_public => false)
41 changeset = create(:changeset, :user => user)
42 node = create(:node, :latitude => 0, :longitude => 0)
47 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
52 auth_header = bearer_authorization_header user
54 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
56 assert_response :forbidden
58 assert_no_changes_in changeset
61 assert_equal 1, node.version
62 assert_equal 0, node.latitude
63 assert_equal 0, node.longitude
66 def test_upload_without_required_scope
68 changeset = create(:changeset, :user => user)
69 node = create(:node, :latitude => 0, :longitude => 0)
74 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
79 auth_header = bearer_authorization_header user, :scopes => %w[read_prefs]
81 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
83 assert_response :forbidden
85 assert_no_changes_in changeset
88 assert_equal 1, node.version
89 assert_equal 0, node.latitude
90 assert_equal 0, node.longitude
93 def test_upload_with_required_scope
95 changeset = create(:changeset, :user => user)
96 node = create(:node, :latitude => 0, :longitude => 0)
101 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
106 auth_header = bearer_authorization_header user, :scopes => %w[write_api]
108 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
110 assert_response :success
112 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
113 assert_dom "> node", 1 do
114 assert_dom "> @old_id", node.id.to_s
115 assert_dom "> @new_id", node.id.to_s
116 assert_dom "> @new_version", "2"
121 assert_equal 1, changeset.num_changes
122 assert_predicate changeset, :num_type_changes_in_sync?
123 assert_equal 1, changeset.num_modified_nodes
126 assert_equal 2, node.version
127 assert_equal 2 * GeoRecord::SCALE, node.latitude
128 assert_equal 1 * GeoRecord::SCALE, node.longitude
132 # try to upload with commands other than create, modify, or delete
133 def test_upload_unknown_action
134 changeset = create(:changeset)
139 <node id='1' lon='1' lat='1' changeset='#{changeset.id}' />
144 auth_header = bearer_authorization_header changeset.user
146 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
148 assert_response :bad_request
149 assert_equal "Unknown action ping, choices are create, modify, delete", @response.body
151 assert_no_changes_in changeset
155 # test for issues in https://github.com/openstreetmap/trac-tickets/issues/1568
156 def test_upload_empty_changeset
157 changeset = create(:changeset)
159 auth_header = bearer_authorization_header changeset.user
162 "<osmChange></osmChange>",
163 "<osmChange><modify/></osmChange>",
164 "<osmChange><modify></modify></osmChange>"].each do |diff|
165 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
167 assert_response :success
170 assert_no_changes_in changeset
174 # test that the X-Error-Format header works to request XML errors
175 def test_upload_xml_errors
176 changeset = create(:changeset)
178 create(:relation_member, :member => node)
180 # try and delete a node that is in use
181 diff = XML::Document.new
182 diff.root = XML::Node.new "osmChange"
183 delete = XML::Node.new "delete"
185 delete << xml_node_for_node(node)
187 auth_header = bearer_authorization_header changeset.user
188 error_header = error_format_header "xml"
190 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header.merge(error_header)
192 assert_response :success
194 assert_dom "osmError[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1
195 assert_dom "osmError>status", 1
196 assert_dom "osmError>message", 1
199 # -------------------------------------
200 # Test creating elements.
201 # -------------------------------------
203 def test_upload_create_node
205 changeset = create(:changeset, :user => user)
210 <node id='-1' lon='30' lat='60' changeset='#{changeset.id}'>
211 <tag k='amenity' v='bar'/>
212 <tag k='name' v='Foo'/>
218 auth_header = bearer_authorization_header user
220 assert_difference "Node.count" => 1,
221 "OldNode.count" => 1,
222 "NodeTag.count" => 2,
223 "OldNodeTag.count" => 2 do
224 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
226 assert_response :success
230 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
231 assert_dom "> node", 1 do |(node_el)|
232 node = Node.find(node_el["new_id"].to_i)
233 assert_dom "> @old_id", "-1"
234 assert_dom "> @new_version", "1"
239 assert_equal 1, changeset.num_changes
240 assert_predicate changeset, :num_type_changes_in_sync?
241 assert_equal 1, changeset.num_created_nodes
243 assert_equal 1, node.version
244 assert_equal changeset, node.changeset
245 assert_predicate node, :visible?
246 assert_equal({ "name" => "Foo", "amenity" => "bar" }, node.tags)
247 assert_equal 60, node.lat
248 assert_equal 30, node.lon
251 def test_upload_create_way
252 node1 = create(:node)
253 node2 = create(:node)
255 changeset = create(:changeset, :user => user)
260 <way id='-1' changeset='#{changeset.id}'>
261 <tag k='highway' v='primary'/>
262 <tag k='name' v='Foo'/>
263 <nd ref='#{node1.id}'/>
264 <nd ref='#{node2.id}'/>
270 auth_header = bearer_authorization_header user
272 assert_difference "Way.count" => 1,
275 "OldWayTag.count" => 2,
276 "WayNode.count" => 2,
277 "OldWayNode.count" => 2 do
278 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
280 assert_response :success
284 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
285 assert_dom "> way", 1 do |(way_el)|
286 way = Way.find(way_el["new_id"].to_i)
287 assert_dom "> @old_id", "-1"
288 assert_dom "> @new_version", "1"
293 assert_equal 1, changeset.num_changes
294 assert_predicate changeset, :num_type_changes_in_sync?
295 assert_equal 1, changeset.num_created_ways
297 assert_equal 1, way.version
298 assert_equal changeset, way.changeset
299 assert_predicate way, :visible?
300 assert_equal({ "name" => "Foo", "highway" => "primary" }, way.tags)
301 assert_equal [node1, node2], way.nodes
304 def test_upload_create_relation
305 node1 = create(:node)
306 way1 = create(:way_with_nodes)
307 relation1 = create(:relation)
309 changeset = create(:changeset, :user => user)
314 <relation id='-1' changeset='#{changeset.id}'>
315 <member type='node' role='n_role' ref='#{node1.id}'/>
316 <member type='way' role='w_role' ref='#{way1.id}'/>
317 <member type='relation' role='r_role' ref='#{relation1.id}'/>
318 <tag k='type' v='collection'/>
324 auth_header = bearer_authorization_header user
326 assert_difference "Relation.count" => 1,
327 "OldRelation.count" => 1,
328 "RelationTag.count" => 1,
329 "OldRelationTag.count" => 1,
330 "RelationMember.count" => 3,
331 "OldRelationMember.count" => 3 do
332 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
334 assert_response :success
338 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
339 assert_dom "> relation", 1 do |(relation_el)|
340 relation = Relation.find(relation_el["new_id"].to_i)
341 assert_dom "> @old_id", "-1"
342 assert_dom "> @new_version", "1"
347 assert_equal 1, changeset.num_changes
348 assert_predicate changeset, :num_type_changes_in_sync?
349 assert_equal 1, changeset.num_created_relations
351 assert_equal 1, relation.version
352 assert_equal changeset, relation.changeset
353 assert_predicate relation, :visible?
354 assert_equal({ "type" => "collection" }, relation.tags)
355 assert_equal [["Node", node1.id, "n_role"],
356 ["Way", way1.id, "w_role"],
357 ["Relation", relation1.id, "r_role"]], relation.members
360 def test_upload_create_elements
362 changeset = create(:changeset, :user => user)
364 way = create(:way_with_nodes, :nodes_count => 2)
365 relation = create(:relation)
370 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
371 <tag k='foo' v='bar'/>
372 <tag k='baz' v='bat'/>
374 <way id='-1' changeset='#{changeset.id}'>
375 <nd ref='#{node.id}'/>
379 <relation id='-1' changeset='#{changeset.id}'>
380 <member type='way' role='some' ref='#{way.id}'/>
381 <member type='node' role='some' ref='#{node.id}'/>
382 <member type='relation' role='some' ref='#{relation.id}'/>
388 auth_header = bearer_authorization_header user
390 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
392 assert_response :success
394 new_node_id, new_way_id, new_rel_id = nil
395 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
396 # inspect the response to find out what the new element IDs are
397 # check the old IDs are all present and negative one
398 # check the versions are present and equal one
399 assert_dom "> node", 1 do |(node_el)|
400 new_node_id = node_el["new_id"].to_i
401 assert_dom "> @old_id", "-1"
402 assert_dom "> @new_version", "1"
404 assert_dom "> way", 1 do |(way_el)|
405 new_way_id = way_el["new_id"].to_i
406 assert_dom "> @old_id", "-1"
407 assert_dom "> @new_version", "1"
409 assert_dom "> relation", 1 do |(rel_el)|
410 new_rel_id = rel_el["new_id"].to_i
411 assert_dom "> @old_id", "-1"
412 assert_dom "> @new_version", "1"
417 assert_equal 3, changeset.num_changes
418 assert_predicate changeset, :num_type_changes_in_sync?
419 assert_equal 1, changeset.num_created_nodes
420 assert_equal 1, changeset.num_created_ways
421 assert_equal 1, changeset.num_created_relations
423 assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
424 assert_equal 0, Way.find(new_way_id).tags.size, "new way should have no tags"
425 assert_equal 0, Relation.find(new_rel_id).tags.size, "new relation should have no tags"
429 # upload an element with a really long tag value
430 def test_upload_create_node_with_tag_too_long
431 changeset = create(:changeset)
436 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
437 <tag k='foo' v='#{'x' * 256}'/>
443 auth_header = bearer_authorization_header changeset.user
445 assert_no_difference "Node.count" do
446 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
448 assert_response :bad_request
451 assert_no_changes_in changeset
454 def test_upload_create_nodes_with_invalid_placeholder_reuse_in_one_action_block
455 changeset = create(:changeset)
460 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}' version='1'/>
461 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
466 auth_header = bearer_authorization_header changeset.user
468 assert_no_difference "Node.count" do
469 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
471 assert_response :bad_request
474 assert_no_changes_in changeset
477 def test_upload_create_nodes_with_invalid_placeholder_reuse_in_two_action_blocks
478 changeset = create(:changeset)
483 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}' version='1'/>
486 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
491 auth_header = bearer_authorization_header changeset.user
493 assert_no_difference "Node.count" do
494 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
496 assert_response :bad_request
499 assert_no_changes_in changeset
502 def test_upload_create_way_referring_node_placeholder_defined_later
503 changeset = create(:changeset)
508 <way id="-1" changeset="#{changeset.id}">
511 <node id="-1" lat="1" lon="2" changeset="#{changeset.id}"/>
516 auth_header = bearer_authorization_header changeset.user
518 assert_no_difference "Node.count" do
519 assert_no_difference "Way.count" do
520 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
522 assert_response :bad_request
525 assert_equal "Placeholder node not found for reference -1 in way -1", @response.body
527 assert_no_changes_in changeset
530 def test_upload_create_way_referring_undefined_node_placeholder
531 changeset = create(:changeset)
536 <way id="-1" changeset="#{changeset.id}">
543 auth_header = bearer_authorization_header changeset.user
545 assert_no_difference "Way.count" do
546 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
548 assert_response :bad_request
550 assert_equal "Placeholder node not found for reference -1 in way -1", @response.body
552 assert_no_changes_in changeset
555 def test_upload_create_existing_way_referring_undefined_node_placeholder
556 changeset = create(:changeset)
562 <way id="#{way.id}" changeset="#{changeset.id}" version="1">
569 auth_header = bearer_authorization_header changeset.user
571 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
573 assert_response :bad_request
574 assert_equal "Placeholder node not found for reference -1 in way #{way.id}", @response.body
576 assert_no_changes_in changeset
579 assert_equal 1, way.version
582 def test_upload_create_relation_referring_undefined_node_placeholder
583 changeset = create(:changeset)
588 <relation id="-1" changeset="#{changeset.id}" version="1">
589 <member type="node" role="foo" ref="-1"/>
595 auth_header = bearer_authorization_header changeset.user
597 assert_no_difference "Relation.count" do
598 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
600 assert_response :bad_request
602 assert_equal "Placeholder Node not found for reference -1 in relation -1.", @response.body
604 assert_no_changes_in changeset
607 def test_upload_create_existing_relation_referring_undefined_way_placeholder
608 changeset = create(:changeset)
609 relation = create(:relation)
614 <relation id="#{relation.id}" changeset="#{changeset.id}" version="1">
615 <member type="way" role="bar" ref="-1"/>
621 auth_header = bearer_authorization_header changeset.user
623 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
625 assert_response :bad_request
626 assert_equal "Placeholder Way not found for reference -1 in relation #{relation.id}.", @response.body
628 assert_no_changes_in changeset
631 assert_equal 1, relation.version
634 def test_upload_create_relations_with_circular_references
635 changeset = create(:changeset)
638 <osmChange version='0.6'>
640 <relation id='-2' version='0' changeset='#{changeset.id}'>
641 <member type='relation' role='' ref='-4' />
642 <tag k='type' v='route' />
643 <tag k='name' v='AtoB' />
645 <relation id='-3' version='0' changeset='#{changeset.id}'>
646 <tag k='type' v='route' />
647 <tag k='name' v='BtoA' />
649 <relation id='-4' version='0' changeset='#{changeset.id}'>
650 <member type='relation' role='' ref='-2' />
651 <member type='relation' role='' ref='-3' />
652 <tag k='type' v='route_master' />
653 <tag k='name' v='master' />
659 auth_header = bearer_authorization_header changeset.user
661 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
663 assert_response :bad_request
664 assert_equal "Placeholder Relation not found for reference -4 in relation -2.", @response.body
666 assert_no_changes_in changeset
669 # -------------------------------------
670 # Test modifying elements.
671 # -------------------------------------
673 def test_upload_modify_node
675 changeset = create(:changeset, :user => user)
676 node = create(:node, :latitude => 0, :longitude => 0)
677 create(:node_tag, :node => node)
682 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
687 auth_header = bearer_authorization_header user
689 assert_difference "Node.count" => 0,
690 "OldNode.count" => 1,
691 "NodeTag.count" => -1,
692 "OldNodeTag.count" => 0 do
693 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
695 assert_response :success
698 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
699 assert_dom "> node", 1 do
700 assert_dom "> @old_id", node.id.to_s
701 assert_dom "> @new_id", node.id.to_s
702 assert_dom "> @new_version", "2"
707 assert_equal 1, changeset.num_changes
708 assert_predicate changeset, :num_type_changes_in_sync?
709 assert_equal 1, changeset.num_modified_nodes
712 assert_equal 2, node.version
713 assert_equal 2 * GeoRecord::SCALE, node.latitude
714 assert_equal 1 * GeoRecord::SCALE, node.longitude
715 assert_equal 0, node.tags.size, "node #{node.id} should now have no tags"
718 def test_upload_modify_way
720 changeset = create(:changeset, :user => user)
722 way = create(:way_with_nodes, :nodes_count => 3)
723 create(:way_tag, :way => way)
728 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
729 <nd ref='#{node.id}'/>
735 auth_header = bearer_authorization_header user
737 assert_difference "Way.count" => 0,
739 "WayTag.count" => -1,
740 "OldWayTag.count" => 0,
741 "WayNode.count" => -2,
742 "OldWayNode.count" => 1 do
743 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
745 assert_response :success
748 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
749 assert_dom "> way", 1 do
750 assert_dom "> @old_id", way.id.to_s
751 assert_dom "> @new_id", way.id.to_s
752 assert_dom "> @new_version", "2"
757 assert_equal 1, changeset.num_changes
758 assert_predicate changeset, :num_type_changes_in_sync?
759 assert_equal 1, changeset.num_modified_ways
762 assert_equal 2, way.version
763 assert_equal 0, way.tags.size, "way #{way.id} should now have no tags"
764 assert_equal [node], way.nodes
767 def test_upload_modify_relation
769 changeset = create(:changeset, :user => user)
771 way = create(:way_with_nodes)
772 relation = create(:relation)
773 other_relation = create(:relation)
774 create(:relation_tag, :relation => relation)
779 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'>
780 <member type='way' role='some' ref='#{way.id}'/>
781 <member type='node' role='some' ref='#{node.id}'/>
782 <member type='relation' role='some' ref='#{other_relation.id}'/>
788 auth_header = bearer_authorization_header user
790 assert_difference "Relation.count" => 0,
791 "OldRelation.count" => 1,
792 "RelationTag.count" => -1,
793 "OldRelationTag.count" => 0,
794 "RelationMember.count" => 3,
795 "OldRelationMember.count" => 3 do
796 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
798 assert_response :success
801 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
802 assert_dom "> relation", 1 do
803 assert_dom "> @old_id", relation.id.to_s
804 assert_dom "> @new_id", relation.id.to_s
805 assert_dom "> @new_version", "2"
810 assert_equal 1, changeset.num_changes
811 assert_predicate changeset, :num_type_changes_in_sync?
812 assert_equal 1, changeset.num_modified_relations
815 assert_equal 2, relation.version
816 assert_equal 0, relation.tags.size, "relation #{relation.id} should now have no tags"
817 assert_equal [["Way", way.id, "some"], ["Node", node.id, "some"], ["Relation", other_relation.id, "some"]], relation.members
820 def test_upload_modify_elements
822 changeset = create(:changeset, :user => user)
823 node = create(:node, :latitude => 0, :longitude => 0)
825 relation = create(:relation)
826 other_relation = create(:relation)
828 # create some tags, since we test that they are removed later
829 create(:node_tag, :node => node)
830 create(:way_tag, :way => way)
831 create(:relation_tag, :relation => relation)
833 # simple diff to change a node, way and relation by removing their tags
837 <node id='#{node.id}' lon='1' lat='2' changeset='#{changeset.id}' version='1'/>
838 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
839 <nd ref='#{node.id}'/>
843 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'>
844 <member type='way' role='some' ref='#{way.id}'/>
845 <member type='node' role='some' ref='#{node.id}'/>
846 <member type='relation' role='some' ref='#{other_relation.id}'/>
852 auth_header = bearer_authorization_header user
854 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
856 assert_response :success
858 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
859 assert_dom "> node", 1 do
860 assert_dom "> @old_id", node.id.to_s
861 assert_dom "> @new_id", node.id.to_s
862 assert_dom "> @new_version", "2"
864 assert_dom "> way", 1 do
865 assert_dom "> @old_id", way.id.to_s
866 assert_dom "> @new_id", way.id.to_s
867 assert_dom "> @new_version", "2"
869 assert_dom "> relation", 1 do
870 assert_dom "> @old_id", relation.id.to_s
871 assert_dom "> @new_id", relation.id.to_s
872 assert_dom "> @new_version", "2"
877 assert_equal 3, changeset.num_changes
878 assert_predicate changeset, :num_type_changes_in_sync?
879 assert_equal 1, changeset.num_modified_nodes
880 assert_equal 1, changeset.num_modified_ways
881 assert_equal 1, changeset.num_modified_relations
884 assert_equal 2, node.version
885 assert_equal 2 * GeoRecord::SCALE, node.latitude
886 assert_equal 1 * GeoRecord::SCALE, node.longitude
887 assert_equal 0, node.tags.size, "node #{node.id} should now have no tags"
889 assert_equal 2, way.version
890 assert_equal 0, way.tags.size, "way #{way.id} should now have no tags"
891 assert_equal [node], way.nodes
893 assert_equal 2, relation.version
894 assert_equal 0, relation.tags.size, "relation #{relation.id} should now have no tags"
895 assert_equal [["Way", way.id, "some"], ["Node", node.id, "some"], ["Relation", other_relation.id, "some"]], relation.members
899 # upload multiple versions of the same element in the same diff.
900 def test_upload_modify_multiple_node_versions
902 changeset = create(:changeset)
904 # change the location of a node multiple times, each time referencing
905 # the last version. doesn't this depend on version numbers being
910 <node id='#{node.id}' lon='0.0' lat='0.0' changeset='#{changeset.id}' version='1'/>
911 <node id='#{node.id}' lon='0.1' lat='0.0' changeset='#{changeset.id}' version='2'/>
912 <node id='#{node.id}' lon='0.1' lat='0.1' changeset='#{changeset.id}' version='3'/>
913 <node id='#{node.id}' lon='0.1' lat='0.2' changeset='#{changeset.id}' version='4'/>
914 <node id='#{node.id}' lon='0.2' lat='0.2' changeset='#{changeset.id}' version='5'/>
915 <node id='#{node.id}' lon='0.3' lat='0.2' changeset='#{changeset.id}' version='6'/>
916 <node id='#{node.id}' lon='0.3' lat='0.3' changeset='#{changeset.id}' version='7'/>
917 <node id='#{node.id}' lon='0.9' lat='0.9' changeset='#{changeset.id}' version='8'/>
922 auth_header = bearer_authorization_header changeset.user
924 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
926 assert_response :success
928 assert_dom "diffResult>node", 8
931 assert_equal 8, changeset.num_changes
932 assert_predicate changeset, :num_type_changes_in_sync?
933 assert_equal 8, changeset.num_modified_nodes
936 assert_equal 9, node.version
937 assert_equal 0.9 * GeoRecord::SCALE, node.latitude
938 assert_equal 0.9 * GeoRecord::SCALE, node.longitude
942 # upload multiple versions of the same element in the same diff, but
943 # keep the version numbers the same.
944 def test_upload_modify_duplicate_node_versions
945 node = create(:node, :latitude => 0, :longitude => 0)
946 changeset = create(:changeset)
951 <node id='#{node.id}' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
952 <node id='#{node.id}' lon='2' lat='2' changeset='#{changeset.id}' version='1'/>
957 auth_header = bearer_authorization_header changeset.user
959 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
961 assert_response :conflict
963 assert_no_changes_in changeset
966 assert_equal 1, node.version
967 assert_equal 0, node.latitude
968 assert_equal 0, node.longitude
972 # try to upload some elements without specifying the version
973 def test_upload_modify_missing_node_version
974 node = create(:node, :latitude => 0, :longitude => 0)
975 changeset = create(:changeset)
980 <node id='#{node.id}' lon='1' lat='1' changeset='#{changeset.id}'/>
985 auth_header = bearer_authorization_header changeset.user
987 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
989 assert_response :bad_request
991 assert_no_changes_in changeset
994 assert_equal 1, node.version
995 assert_equal 0, node.latitude
996 assert_equal 0, node.longitude
1000 # create a diff which references several changesets, which should cause
1001 # a rollback and none of the diff gets committed
1002 def test_upload_modify_with_references_to_different_changesets
1003 changeset1 = create(:changeset)
1004 changeset2 = create(:changeset, :user => changeset1.user)
1005 node1 = create(:node)
1006 node2 = create(:node)
1008 # simple diff to create a node way and relation using placeholders
1012 <node id='#{node1.id}' lon='0' lat='0' changeset='#{changeset1.id}' version='1'/>
1015 <node id='#{node2.id}' lon='0' lat='0' changeset='#{changeset2.id}' version='1'/>
1020 auth_header = bearer_authorization_header changeset1.user
1022 post api_changeset_upload_path(changeset1), :params => diff, :headers => auth_header
1024 assert_response :conflict
1026 assert_no_changes_in changeset1
1027 assert_no_changes_in changeset2
1029 assert_nodes_are_equal(node1, Node.find(node1.id))
1030 assert_nodes_are_equal(node2, Node.find(node2.id))
1034 # upload a valid changeset which has a mixture of whitespace
1035 # to check a bug https://github.com/openstreetmap/trac-tickets/issues/1565
1036 def test_upload_modify_with_mixed_whitespace
1037 changeset = create(:changeset)
1038 node = create(:node)
1039 way = create(:way_with_nodes, :nodes_count => 2)
1040 relation = create(:relation)
1041 other_relation = create(:relation)
1042 create(:relation_tag, :relation => relation)
1046 <modify><node id='#{node.id}' lon='0' lat='0' changeset='#{changeset.id}'
1048 <node id='#{node.id}' lon='1' lat='1' changeset='#{changeset.id}' version='2'><tag k='k' v='v'/></node></modify>
1050 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'><member
1051 type='way' role='some' ref='#{way.id}'/><member
1052 type='node' role='some' ref='#{node.id}'/>
1053 <member type='relation' role='some' ref='#{other_relation.id}'/>
1055 </modify></osmChange>
1058 auth_header = bearer_authorization_header changeset.user
1060 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1062 assert_response :success
1064 assert_dom "diffResult>node", 2
1065 assert_dom "diffResult>relation", 1
1068 assert_equal 3, changeset.num_changes
1069 assert_predicate changeset, :num_type_changes_in_sync?
1070 assert_equal 2, changeset.num_modified_nodes
1071 assert_equal 1, changeset.num_modified_relations
1073 assert_equal 1, Node.find(node.id).tags.size, "node #{node.id} should now have one tag"
1074 assert_equal 0, Relation.find(relation.id).tags.size, "relation #{relation.id} should now have no tags"
1077 def test_upload_modify_unknown_node_placeholder
1078 check_upload_results_in_not_found do |changeset|
1079 "<modify><node id='-1' lon='0' lat='0' changeset='#{changeset.id}' version='1'/></modify>"
1083 def test_upload_modify_unknown_way_placeholder
1084 check_upload_results_in_not_found do |changeset|
1085 "<modify><way id='-1' changeset='#{changeset.id}' version='1'/></modify>"
1089 def test_upload_modify_unknown_relation_placeholder
1090 check_upload_results_in_not_found do |changeset|
1091 "<modify><relation id='-1' changeset='#{changeset.id}' version='1'/></modify>"
1095 # -------------------------------------
1096 # Test deleting elements.
1097 # -------------------------------------
1099 def test_upload_delete_node
1100 changeset = create(:changeset)
1101 node = create(:node, :lat => 0, :lon => 0)
1102 create(:node_tag, :node => node)
1107 <node id='#{node.id}' changeset='#{changeset.id}' version='1' lat='0' lon='0'/>
1112 auth_header = bearer_authorization_header changeset.user
1114 assert_difference "Node.count" => 0,
1115 "OldNode.count" => 1,
1116 "NodeTag.count" => -1,
1117 "OldNodeTag.count" => 0 do
1118 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1120 assert_response :success
1123 assert_dom "diffResult", 1 do
1124 assert_dom "> node", 1 do
1125 assert_dom "> @old_id", node.id.to_s
1130 assert_equal 1, changeset.num_changes
1131 assert_predicate changeset, :num_type_changes_in_sync?
1132 assert_equal 1, changeset.num_deleted_nodes
1135 assert_not_predicate node, :visible?
1138 def test_upload_delete_way
1139 changeset = create(:changeset)
1140 way = create(:way_with_nodes, :nodes_count => 3)
1141 create(:way_tag, :way => way)
1146 <way id='#{way.id}' changeset='#{changeset.id}' version='1'/>
1151 auth_header = bearer_authorization_header changeset.user
1153 assert_difference "Way.count" => 0,
1154 "OldWay.count" => 1,
1155 "WayTag.count" => -1,
1156 "OldWayTag.count" => 0,
1157 "WayNode.count" => -3,
1158 "OldWayNode.count" => 0 do
1159 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1161 assert_response :success
1164 assert_dom "diffResult", 1 do
1165 assert_dom "> way", 1 do
1166 assert_dom "> @old_id", way.id.to_s
1171 assert_equal 1, changeset.num_changes
1172 assert_predicate changeset, :num_type_changes_in_sync?
1173 assert_equal 1, changeset.num_deleted_ways
1176 assert_not_predicate way, :visible?
1179 def test_upload_delete_relation
1180 changeset = create(:changeset)
1181 relation = create(:relation)
1182 create(:relation_member, :relation => relation, :member => create(:node))
1183 create(:relation_tag, :relation => relation)
1188 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'/>
1193 auth_header = bearer_authorization_header changeset.user
1195 assert_difference "Relation.count" => 0,
1196 "OldRelation.count" => 1,
1197 "RelationTag.count" => -1,
1198 "OldRelationTag.count" => 0,
1199 "RelationMember.count" => -1,
1200 "OldRelationMember.count" => 0 do
1201 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1203 assert_response :success
1206 assert_dom "diffResult", 1 do
1207 assert_dom "> relation", 1 do
1208 assert_dom "> @old_id", relation.id.to_s
1213 assert_not_predicate relation, :visible?
1217 # test a complex delete where we delete elements which rely on each other
1218 # in the same transaction.
1219 def test_upload_delete_elements
1220 changeset = create(:changeset)
1221 super_relation = create(:relation)
1222 used_relation = create(:relation)
1223 used_way = create(:way)
1224 used_node = create(:node)
1225 create(:relation_member, :relation => super_relation, :member => used_relation)
1226 create(:relation_member, :relation => super_relation, :member => used_way)
1227 create(:relation_member, :relation => super_relation, :member => used_node)
1229 diff = XML::Document.new
1230 diff.root = XML::Node.new "osmChange"
1231 delete = XML::Node.new "delete"
1233 delete << xml_node_for_relation(super_relation)
1234 delete << xml_node_for_relation(used_relation)
1235 delete << xml_node_for_way(used_way)
1236 delete << xml_node_for_node(used_node)
1237 %w[node way relation].each do |type|
1238 delete.find("//osmChange/delete/#{type}").each do |n|
1239 n["changeset"] = changeset.id.to_s
1243 auth_header = bearer_authorization_header changeset.user
1245 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1247 assert_response :success
1249 assert_dom "diffResult", 1 do
1250 assert_dom "> node", 1
1251 assert_dom "> way", 1
1252 assert_dom "> relation", 2
1255 assert_not Node.find(used_node.id).visible
1256 assert_not Way.find(used_way.id).visible
1257 assert_not Relation.find(super_relation.id).visible
1258 assert_not Relation.find(used_relation.id).visible
1262 # test uploading a delete with no lat/lon, as they are optional in the osmChange spec.
1263 def test_upload_delete_node_without_latlon
1264 node = create(:node)
1265 changeset = create(:changeset)
1267 diff = "<osmChange><delete><node id='#{node.id}' version='#{node.version}' changeset='#{changeset.id}'/></delete></osmChange>"
1269 auth_header = bearer_authorization_header changeset.user
1271 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1273 assert_response :success
1275 assert_dom "diffResult", 1 do
1276 assert_dom "> node", 1 do
1277 assert_dom "> @old_id", node.id.to_s
1278 assert_dom "> @new_id", 0
1279 assert_dom "> @new_version", 0
1284 assert_equal 1, changeset.num_changes
1285 assert_predicate changeset, :num_type_changes_in_sync?
1286 assert_equal 1, changeset.num_deleted_nodes
1289 assert_not node.visible
1293 # test that deleting stuff in a transaction doesn't bypass the checks
1294 # to ensure that used elements are not deleted.
1295 def test_upload_delete_referenced_elements
1296 changeset = create(:changeset)
1297 relation = create(:relation)
1298 other_relation = create(:relation)
1299 used_way = create(:way)
1300 used_node = create(:node)
1301 create(:relation_member, :relation => relation, :member => used_way)
1302 create(:relation_member, :relation => relation, :member => used_node)
1304 diff = XML::Document.new
1305 diff.root = XML::Node.new "osmChange"
1306 delete = XML::Node.new "delete"
1308 delete << xml_node_for_relation(other_relation)
1309 delete << xml_node_for_way(used_way)
1310 delete << xml_node_for_node(used_node)
1311 %w[node way relation].each do |type|
1312 delete.find("//osmChange/delete/#{type}").each do |n|
1313 n["changeset"] = changeset.id.to_s
1317 auth_header = bearer_authorization_header changeset.user
1319 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1321 assert_response :precondition_failed
1322 assert_equal "Precondition failed: Way #{used_way.id} is still used by relations #{relation.id}.", @response.body
1324 assert_no_changes_in changeset
1326 assert Node.find(used_node.id).visible
1327 assert Way.find(used_way.id).visible
1328 assert Relation.find(relation.id).visible
1329 assert Relation.find(other_relation.id).visible
1333 # test that a conditional delete of an in use object works.
1334 def test_upload_delete_if_unused
1335 changeset = create(:changeset)
1336 super_relation = create(:relation)
1337 used_relation = create(:relation)
1338 used_way = create(:way)
1339 used_node = create(:node)
1340 create(:relation_member, :relation => super_relation, :member => used_relation)
1341 create(:relation_member, :relation => super_relation, :member => used_way)
1342 create(:relation_member, :relation => super_relation, :member => used_node)
1344 diff = XML::Document.new
1345 diff.root = XML::Node.new "osmChange"
1346 delete = XML::Node.new "delete"
1348 delete["if-unused"] = ""
1349 delete << xml_node_for_relation(used_relation)
1350 delete << xml_node_for_way(used_way)
1351 delete << xml_node_for_node(used_node)
1352 %w[node way relation].each do |type|
1353 delete.find("//osmChange/delete/#{type}").each do |n|
1354 n["changeset"] = changeset.id.to_s
1358 auth_header = bearer_authorization_header changeset.user
1360 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1362 assert_response :success
1364 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
1365 assert_dom "> node", 1 do
1366 assert_dom "> @old_id", used_node.id.to_s
1367 assert_dom "> @new_id", used_node.id.to_s
1368 assert_dom "> @new_version", used_node.version.to_s
1370 assert_dom "> way", 1 do
1371 assert_dom "> @old_id", used_way.id.to_s
1372 assert_dom "> @new_id", used_way.id.to_s
1373 assert_dom "> @new_version", used_way.version.to_s
1375 assert_dom "> relation", 1 do
1376 assert_dom "> @old_id", used_relation.id.to_s
1377 assert_dom "> @new_id", used_relation.id.to_s
1378 assert_dom "> @new_version", used_relation.version.to_s
1382 assert_no_changes_in changeset
1384 assert Node.find(used_node.id).visible
1385 assert Way.find(used_way.id).visible
1386 assert Relation.find(used_relation.id).visible
1389 def test_upload_delete_with_multiple_blocks_and_if_unused
1390 changeset = create(:changeset)
1391 node = create(:node)
1393 create(:way_node, :way => way, :node => node)
1394 alone_node = create(:node)
1397 <osmChange version='0.6'>
1398 <delete version="0.6">
1399 <node id="#{node.id}" version="#{node.version}" changeset="#{changeset.id}"/>
1401 <delete version="0.6" if-unused="true">
1402 <node id="#{alone_node.id}" version="#{alone_node.version}" changeset="#{changeset.id}"/>
1407 auth_header = bearer_authorization_header changeset.user
1409 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1411 assert_response :precondition_failed
1412 assert_equal "Precondition failed: Node #{node.id} is still used by ways #{way.id}.", @response.body
1414 assert_no_changes_in changeset
1417 def test_upload_delete_unknown_node_placeholder
1418 check_upload_results_in_not_found do |changeset|
1419 "<delete><node id='-1' changeset='#{changeset.id}' version='1'/></delete>"
1423 def test_upload_delete_unknown_way_placeholder
1424 check_upload_results_in_not_found do |changeset|
1425 "<delete><way id='-1' changeset='#{changeset.id}' version='1'/></delete>"
1429 def test_upload_delete_unknown_relation_placeholder
1430 check_upload_results_in_not_found do |changeset|
1431 "<delete><relation id='-1' changeset='#{changeset.id}' version='1'/></delete>"
1435 # -------------------------------------
1436 # Test combined element changes.
1437 # -------------------------------------
1440 # upload something which creates new objects and inserts them into
1441 # existing containers using placeholders.
1442 def test_upload_create_and_insert_elements
1444 node = create(:node)
1445 relation = create(:relation)
1446 create(:way_node, :way => way, :node => node)
1447 changeset = create(:changeset)
1452 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1453 <tag k='foo' v='bar'/>
1454 <tag k='baz' v='bat'/>
1458 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
1460 <nd ref='#{node.id}'/>
1462 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'>
1463 <member type='way' role='some' ref='#{way.id}'/>
1464 <member type='node' role='some' ref='-1'/>
1465 <member type='relation' role='some' ref='#{relation.id}'/>
1471 auth_header = bearer_authorization_header changeset.user
1473 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1475 assert_response :success
1478 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
1479 assert_dom "> node", 1 do |(node_el)|
1480 new_node_id = node_el["new_id"].to_i
1482 assert_dom "> way", 1
1483 assert_dom "> relation", 1
1487 assert_equal 3, changeset.num_changes
1488 assert_predicate changeset, :num_type_changes_in_sync?
1489 assert_equal 1, changeset.num_created_nodes
1490 assert_equal 1, changeset.num_modified_ways
1491 assert_equal 1, changeset.num_modified_relations
1493 assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
1494 assert_equal [new_node_id, node.id], Way.find(way.id).nds, "way nodes should match"
1495 Relation.find(relation.id).members.each do |type, id, _role|
1496 assert_equal new_node_id, id, "relation should contain new node" if type == "node"
1501 # test that a placeholder can be reused within the same upload.
1502 def test_upload_create_modify_delete_node_reusing_placeholder
1503 changeset = create(:changeset)
1508 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1509 <tag k="foo" v="bar"/>
1513 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
1516 <node id='-1' lon='2' lat='2' changeset='#{changeset.id}' version='2'/>
1521 auth_header = bearer_authorization_header changeset.user
1523 assert_difference "Node.count", 1 do
1524 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1526 assert_response :success
1529 assert_dom "diffResult>node", 3
1530 assert_dom "diffResult>node[old_id='-1']", 3
1533 assert_equal 3, changeset.num_changes
1534 assert_predicate changeset, :num_type_changes_in_sync?
1535 assert_equal 1, changeset.num_created_nodes
1536 assert_equal 1, changeset.num_modified_nodes
1537 assert_equal 1, changeset.num_deleted_nodes
1540 assert_equal 3, node.version
1541 assert_not node.visible
1544 def test_upload_create_and_duplicate_delete
1545 changeset = create(:changeset)
1550 <node id="-1" lat="39" lon="116" changeset="#{changeset.id}" />
1553 <node id="-1" version="1" changeset="#{changeset.id}" />
1554 <node id="-1" version="1" changeset="#{changeset.id}" />
1559 auth_header = bearer_authorization_header changeset.user
1561 assert_no_difference "Node.count" do
1562 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1564 assert_response :gone
1567 assert_no_changes_in changeset
1570 def test_upload_create_and_duplicate_delete_if_unused
1571 changeset = create(:changeset)
1576 <node id="-1" lat="39" lon="116" changeset="#{changeset.id}" />
1578 <delete if-unused="true">
1579 <node id="-1" version="1" changeset="#{changeset.id}" />
1580 <node id="-1" version="1" changeset="#{changeset.id}" />
1585 auth_header = bearer_authorization_header changeset.user
1587 assert_difference "Node.count", 1 do
1588 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1590 assert_response :success
1593 assert_dom "diffResult>node", 3
1594 assert_dom "diffResult>node[old_id='-1']", 3
1595 assert_dom "diffResult>node[new_version='1']", 1
1596 assert_dom "diffResult>node[new_version='2']", 1
1599 assert_equal 2, changeset.num_changes
1600 assert_predicate changeset, :num_type_changes_in_sync?
1601 assert_equal 1, changeset.num_created_nodes
1602 assert_equal 1, changeset.num_deleted_nodes
1605 assert_equal 2, node.version
1606 assert_not node.visible
1609 # -------------------------------------
1610 # Test bounding boxes.
1611 # -------------------------------------
1613 def test_upload_bbox_of_widely_spaced_nodes
1614 user = create(:user)
1616 # create an old changeset to ensure we have the maximum rate limit
1617 create(:changeset, :user => user, :created_at => Time.now.utc - 28.days)
1619 changeset = create(:changeset, :user => user)
1621 # upload some widely-spaced nodes, spiralling positive and negative
1625 <node id='-1' lon='-20' lat='-10' changeset='#{changeset.id}'/>
1626 <node id='-10' lon='20' lat='10' changeset='#{changeset.id}'/>
1627 <node id='-2' lon='-40' lat='-20' changeset='#{changeset.id}'/>
1628 <node id='-11' lon='40' lat='20' changeset='#{changeset.id}'/>
1629 <node id='-3' lon='-60' lat='-30' changeset='#{changeset.id}'/>
1630 <node id='-12' lon='60' lat='30' changeset='#{changeset.id}'/>
1631 <node id='-4' lon='-80' lat='-40' changeset='#{changeset.id}'/>
1632 <node id='-13' lon='80' lat='40' changeset='#{changeset.id}'/>
1633 <node id='-5' lon='-100' lat='-50' changeset='#{changeset.id}'/>
1634 <node id='-14' lon='100' lat='50' changeset='#{changeset.id}'/>
1635 <node id='-6' lon='-120' lat='-60' changeset='#{changeset.id}'/>
1636 <node id='-15' lon='120' lat='60' changeset='#{changeset.id}'/>
1637 <node id='-7' lon='-140' lat='-70' changeset='#{changeset.id}'/>
1638 <node id='-16' lon='140' lat='70' changeset='#{changeset.id}'/>
1639 <node id='-8' lon='-160' lat='-80' changeset='#{changeset.id}'/>
1640 <node id='-17' lon='160' lat='80' changeset='#{changeset.id}'/>
1641 <node id='-9' lon='-179.9' lat='-89.9' changeset='#{changeset.id}'/>
1642 <node id='-18' lon='179.9' lat='89.9' changeset='#{changeset.id}'/>
1647 auth_header = bearer_authorization_header user
1649 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1651 assert_response :success
1654 assert_equal 18, changeset.num_changes
1655 assert_predicate changeset, :num_type_changes_in_sync?
1656 assert_equal 18, changeset.num_created_nodes
1658 # check that the changeset bbox is within bounds
1659 assert_operator changeset.min_lon, :>=, -180 * GeoRecord::SCALE, "Minimum longitude (#{changeset.min_lon / GeoRecord::SCALE}) should be >= -180 to be valid."
1660 assert_operator changeset.max_lon, :<=, 180 * GeoRecord::SCALE, "Maximum longitude (#{changeset.max_lon / GeoRecord::SCALE}) should be <= 180 to be valid."
1661 assert_operator changeset.min_lat, :>=, -90 * GeoRecord::SCALE, "Minimum latitude (#{changeset.min_lat / GeoRecord::SCALE}) should be >= -90 to be valid."
1662 assert_operator changeset.max_lat, :<=, 90 * GeoRecord::SCALE, "Maximum latitude (#{changeset.max_lat / GeoRecord::SCALE}) should be <= 90 to be valid."
1665 def test_upload_bbox_of_moved_node
1666 changeset = create(:changeset)
1667 node = create(:node, :lat => 1.0, :lon => 2.0)
1672 <node id='#{node.id}' lat='1.1' lon='2.1' changeset='#{changeset.id}' version='1'/>
1677 auth_header = bearer_authorization_header changeset.user
1679 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1681 assert_response :success
1684 assert_equal 1, changeset.num_changes
1685 assert_predicate changeset, :num_type_changes_in_sync?
1686 assert_equal 1, changeset.num_modified_nodes
1689 assert_equal 1.0 * GeoRecord::SCALE, changeset.min_lat, "min_lat should be 1.0 degrees"
1690 assert_equal 2.0 * GeoRecord::SCALE, changeset.min_lon, "min_lon should be 2.0 degrees"
1691 assert_equal 1.1 * GeoRecord::SCALE, changeset.max_lat, "max_lat should be 1.1 degrees"
1692 assert_equal 2.1 * GeoRecord::SCALE, changeset.max_lon, "max_lon should be 2.1 degrees"
1695 def test_upload_bbox_of_extended_way
1697 initial_node = create(:node, :lat => 1.1, :lon => 2.1)
1698 create(:way_node, :way => way, :node => initial_node)
1699 added_node = create(:node, :lat => 1.3, :lon => 2.3)
1700 changeset = create(:changeset)
1705 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
1706 <nd ref='#{initial_node.id}'/>
1707 <nd ref='#{added_node.id}'/>
1713 auth_header = bearer_authorization_header changeset.user
1715 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1717 assert_response :success
1720 assert_equal 1, changeset.num_changes
1721 assert_predicate changeset, :num_type_changes_in_sync?
1722 assert_equal 1, changeset.num_modified_ways
1725 assert_equal 1.1 * GeoRecord::SCALE, changeset.min_lat, "min_lat should be 1.1 degrees"
1726 assert_equal 2.1 * GeoRecord::SCALE, changeset.min_lon, "min_lon should be 2.1 degrees"
1727 assert_equal 1.3 * GeoRecord::SCALE, changeset.max_lat, "max_lat should be 1.3 degrees"
1728 assert_equal 2.3 * GeoRecord::SCALE, changeset.max_lon, "max_lon should be 2.3 degrees"
1731 # -------------------------------------
1732 # Test upload rate/size limits.
1733 # -------------------------------------
1735 def test_upload_initial_rate_limit
1736 user = create(:user)
1737 node = create(:node)
1738 way = create(:way_with_nodes, :nodes_count => 2)
1739 relation = create(:relation)
1741 # create a changeset that puts us near the initial rate limit
1742 num_changes = Settings.initial_changes_per_hour - 2
1743 changeset = create(:changeset, :user => user,
1744 :created_at => Time.now.utc - 5.minutes,
1745 :num_changes => num_changes,
1746 :num_created_nodes => num_changes)
1751 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1752 <tag k='foo' v='bar'/>
1753 <tag k='baz' v='bat'/>
1755 <way id='-1' changeset='#{changeset.id}'>
1756 <nd ref='#{node.id}'/>
1760 <relation id='-1' changeset='#{changeset.id}'>
1761 <member type='way' role='some' ref='#{way.id}'/>
1762 <member type='node' role='some' ref='#{node.id}'/>
1763 <member type='relation' role='some' ref='#{relation.id}'/>
1769 auth_header = bearer_authorization_header user
1771 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1773 assert_response :too_many_requests, "upload did not hit rate limit"
1776 assert_equal num_changes, changeset.num_changes
1777 assert_predicate changeset, :num_type_changes_in_sync?
1780 def test_upload_maximum_rate_limit
1781 user = create(:user)
1782 node = create(:node)
1783 way = create(:way_with_nodes, :nodes_count => 2)
1784 relation = create(:relation)
1786 # create a changeset to establish our initial edit time
1787 changeset = create(:changeset, :user => user,
1788 :created_at => Time.now.utc - 28.days)
1790 # create changeset to put us near the maximum rate limit
1791 remaining_num_changes = Settings.max_changes_per_hour - 2
1793 while remaining_num_changes.positive?
1794 num_changes = [remaining_num_changes, Changeset::MAX_ELEMENTS].min
1795 changeset = create(:changeset, :user => user,
1796 :created_at => Time.now.utc - 5.minutes,
1797 :num_changes => num_changes,
1798 :num_created_nodes => num_changes)
1799 remaining_num_changes -= num_changes
1805 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1806 <tag k='foo' v='bar'/>
1807 <tag k='baz' v='bat'/>
1809 <way id='-1' changeset='#{changeset.id}'>
1810 <nd ref='#{node.id}'/>
1814 <relation id='-1' changeset='#{changeset.id}'>
1815 <member type='way' role='some' ref='#{way.id}'/>
1816 <member type='node' role='some' ref='#{node.id}'/>
1817 <member type='relation' role='some' ref='#{relation.id}'/>
1823 auth_header = bearer_authorization_header user
1825 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1827 assert_response :too_many_requests, "upload did not hit rate limit"
1830 assert_equal num_changes, changeset.num_changes
1831 assert_predicate changeset, :num_type_changes_in_sync?
1834 def test_upload_initial_size_limit
1835 user = create(:user)
1837 # create a changeset that puts us near the initial size limit
1838 changeset = create(:changeset, :user => user,
1839 :min_lat => (-0.5 * GeoRecord::SCALE).round, :min_lon => (0.5 * GeoRecord::SCALE).round,
1840 :max_lat => (0.5 * GeoRecord::SCALE).round, :max_lon => (2.5 * GeoRecord::SCALE).round)
1845 <node id='-1' lon='0.9' lat='2.9' changeset='#{changeset.id}'>
1846 <tag k='foo' v='bar'/>
1847 <tag k='baz' v='bat'/>
1853 auth_header = bearer_authorization_header user
1855 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1857 assert_response :payload_too_large, "upload did not hit size limit"
1859 assert_no_changes_in changeset
1862 def test_upload_size_limit_after_one_week
1863 user = create(:user)
1865 # create a changeset to establish our initial edit time
1866 create(:changeset, :user => user, :created_at => Time.now.utc - 7.days)
1868 # create a changeset that puts us near the initial size limit
1869 changeset = create(:changeset, :user => user, :bbox => [0.5, -0.5, 2.5, 0.5])
1874 <node id='-1' lon='35' lat='35' changeset='#{changeset.id}'>
1875 <tag k='foo' v='bar'/>
1876 <tag k='baz' v='bat'/>
1882 auth_header = bearer_authorization_header user
1884 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1886 assert_response :payload_too_large, "upload did not hit size limit"
1888 assert_no_changes_in changeset
1893 def check_upload_results_in_not_found(&)
1894 changeset = create(:changeset)
1895 diff = "<osmChange>#{yield changeset}</osmChange>"
1896 auth_header = bearer_authorization_header changeset.user
1898 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1900 assert_response :not_found
1902 assert_no_changes_in changeset
1905 def assert_no_changes_in(changeset)
1907 assert_equal 0, changeset.num_changes
1908 assert_predicate changeset, :num_type_changes_in_sync?