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_equal 1, changeset.num_changes
1214 assert_predicate changeset, :num_type_changes_in_sync?
1215 assert_equal 1, changeset.num_deleted_relations
1218 assert_not_predicate relation, :visible?
1222 # test a complex delete where we delete elements which rely on each other
1223 # in the same transaction.
1224 def test_upload_delete_elements
1225 changeset = create(:changeset)
1226 super_relation = create(:relation)
1227 used_relation = create(:relation)
1228 used_way = create(:way)
1229 used_node = create(:node)
1230 create(:relation_member, :relation => super_relation, :member => used_relation)
1231 create(:relation_member, :relation => super_relation, :member => used_way)
1232 create(:relation_member, :relation => super_relation, :member => used_node)
1234 diff = XML::Document.new
1235 diff.root = XML::Node.new "osmChange"
1236 delete = XML::Node.new "delete"
1238 delete << xml_node_for_relation(super_relation)
1239 delete << xml_node_for_relation(used_relation)
1240 delete << xml_node_for_way(used_way)
1241 delete << xml_node_for_node(used_node)
1242 %w[node way relation].each do |type|
1243 delete.find("//osmChange/delete/#{type}").each do |n|
1244 n["changeset"] = changeset.id.to_s
1248 auth_header = bearer_authorization_header changeset.user
1250 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1252 assert_response :success
1254 assert_dom "diffResult", 1 do
1255 assert_dom "> node", 1
1256 assert_dom "> way", 1
1257 assert_dom "> relation", 2
1261 assert_equal 4, changeset.num_changes
1262 assert_predicate changeset, :num_type_changes_in_sync?
1263 assert_equal 1, changeset.num_deleted_nodes
1264 assert_equal 1, changeset.num_deleted_ways
1265 assert_equal 2, changeset.num_deleted_relations
1267 assert_not Node.find(used_node.id).visible
1268 assert_not Way.find(used_way.id).visible
1269 assert_not Relation.find(super_relation.id).visible
1270 assert_not Relation.find(used_relation.id).visible
1274 # test uploading a delete with no lat/lon, as they are optional in the osmChange spec.
1275 def test_upload_delete_node_without_latlon
1276 node = create(:node)
1277 changeset = create(:changeset)
1279 diff = "<osmChange><delete><node id='#{node.id}' version='#{node.version}' changeset='#{changeset.id}'/></delete></osmChange>"
1281 auth_header = bearer_authorization_header changeset.user
1283 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1285 assert_response :success
1287 assert_dom "diffResult", 1 do
1288 assert_dom "> node", 1 do
1289 assert_dom "> @old_id", node.id.to_s
1290 assert_dom "> @new_id", 0
1291 assert_dom "> @new_version", 0
1296 assert_equal 1, changeset.num_changes
1297 assert_predicate changeset, :num_type_changes_in_sync?
1298 assert_equal 1, changeset.num_deleted_nodes
1301 assert_not node.visible
1305 # test that deleting stuff in a transaction doesn't bypass the checks
1306 # to ensure that used elements are not deleted.
1307 def test_upload_delete_referenced_elements
1308 changeset = create(:changeset)
1309 relation = create(:relation)
1310 other_relation = create(:relation)
1311 used_way = create(:way)
1312 used_node = create(:node)
1313 create(:relation_member, :relation => relation, :member => used_way)
1314 create(:relation_member, :relation => relation, :member => used_node)
1316 diff = XML::Document.new
1317 diff.root = XML::Node.new "osmChange"
1318 delete = XML::Node.new "delete"
1320 delete << xml_node_for_relation(other_relation)
1321 delete << xml_node_for_way(used_way)
1322 delete << xml_node_for_node(used_node)
1323 %w[node way relation].each do |type|
1324 delete.find("//osmChange/delete/#{type}").each do |n|
1325 n["changeset"] = changeset.id.to_s
1329 auth_header = bearer_authorization_header changeset.user
1331 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1333 assert_response :precondition_failed
1334 assert_equal "Precondition failed: Way #{used_way.id} is still used by relations #{relation.id}.", @response.body
1336 assert_no_changes_in changeset
1338 assert Node.find(used_node.id).visible
1339 assert Way.find(used_way.id).visible
1340 assert Relation.find(relation.id).visible
1341 assert Relation.find(other_relation.id).visible
1345 # test that a conditional delete of an in use object works.
1346 def test_upload_delete_if_unused
1347 changeset = create(:changeset)
1348 super_relation = create(:relation)
1349 used_relation = create(:relation)
1350 used_way = create(:way)
1351 used_node = create(:node)
1352 create(:relation_member, :relation => super_relation, :member => used_relation)
1353 create(:relation_member, :relation => super_relation, :member => used_way)
1354 create(:relation_member, :relation => super_relation, :member => used_node)
1356 diff = XML::Document.new
1357 diff.root = XML::Node.new "osmChange"
1358 delete = XML::Node.new "delete"
1360 delete["if-unused"] = ""
1361 delete << xml_node_for_relation(used_relation)
1362 delete << xml_node_for_way(used_way)
1363 delete << xml_node_for_node(used_node)
1364 %w[node way relation].each do |type|
1365 delete.find("//osmChange/delete/#{type}").each do |n|
1366 n["changeset"] = changeset.id.to_s
1370 auth_header = bearer_authorization_header changeset.user
1372 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1374 assert_response :success
1376 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
1377 assert_dom "> node", 1 do
1378 assert_dom "> @old_id", used_node.id.to_s
1379 assert_dom "> @new_id", used_node.id.to_s
1380 assert_dom "> @new_version", used_node.version.to_s
1382 assert_dom "> way", 1 do
1383 assert_dom "> @old_id", used_way.id.to_s
1384 assert_dom "> @new_id", used_way.id.to_s
1385 assert_dom "> @new_version", used_way.version.to_s
1387 assert_dom "> relation", 1 do
1388 assert_dom "> @old_id", used_relation.id.to_s
1389 assert_dom "> @new_id", used_relation.id.to_s
1390 assert_dom "> @new_version", used_relation.version.to_s
1394 assert_no_changes_in changeset
1396 assert Node.find(used_node.id).visible
1397 assert Way.find(used_way.id).visible
1398 assert Relation.find(used_relation.id).visible
1401 def test_upload_delete_with_multiple_blocks_and_if_unused
1402 changeset = create(:changeset)
1403 node = create(:node)
1405 create(:way_node, :way => way, :node => node)
1406 alone_node = create(:node)
1409 <osmChange version='0.6'>
1410 <delete version="0.6">
1411 <node id="#{node.id}" version="#{node.version}" changeset="#{changeset.id}"/>
1413 <delete version="0.6" if-unused="true">
1414 <node id="#{alone_node.id}" version="#{alone_node.version}" changeset="#{changeset.id}"/>
1419 auth_header = bearer_authorization_header changeset.user
1421 post api_changeset_upload_path(changeset), :params => diff.to_s, :headers => auth_header
1423 assert_response :precondition_failed
1424 assert_equal "Precondition failed: Node #{node.id} is still used by ways #{way.id}.", @response.body
1426 assert_no_changes_in changeset
1429 def test_upload_delete_unknown_node_placeholder
1430 check_upload_results_in_not_found do |changeset|
1431 "<delete><node id='-1' changeset='#{changeset.id}' version='1'/></delete>"
1435 def test_upload_delete_unknown_way_placeholder
1436 check_upload_results_in_not_found do |changeset|
1437 "<delete><way id='-1' changeset='#{changeset.id}' version='1'/></delete>"
1441 def test_upload_delete_unknown_relation_placeholder
1442 check_upload_results_in_not_found do |changeset|
1443 "<delete><relation id='-1' changeset='#{changeset.id}' version='1'/></delete>"
1447 # -------------------------------------
1448 # Test combined element changes.
1449 # -------------------------------------
1452 # upload something which creates new objects and inserts them into
1453 # existing containers using placeholders.
1454 def test_upload_create_and_insert_elements
1456 node = create(:node)
1457 relation = create(:relation)
1458 create(:way_node, :way => way, :node => node)
1459 changeset = create(:changeset)
1464 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1465 <tag k='foo' v='bar'/>
1466 <tag k='baz' v='bat'/>
1470 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
1472 <nd ref='#{node.id}'/>
1474 <relation id='#{relation.id}' changeset='#{changeset.id}' version='1'>
1475 <member type='way' role='some' ref='#{way.id}'/>
1476 <member type='node' role='some' ref='-1'/>
1477 <member type='relation' role='some' ref='#{relation.id}'/>
1483 auth_header = bearer_authorization_header changeset.user
1485 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1487 assert_response :success
1490 assert_dom "diffResult[version='#{Settings.api_version}'][generator='#{Settings.generator}']", 1 do
1491 assert_dom "> node", 1 do |(node_el)|
1492 new_node_id = node_el["new_id"].to_i
1494 assert_dom "> way", 1
1495 assert_dom "> relation", 1
1499 assert_equal 3, changeset.num_changes
1500 assert_predicate changeset, :num_type_changes_in_sync?
1501 assert_equal 1, changeset.num_created_nodes
1502 assert_equal 1, changeset.num_modified_ways
1503 assert_equal 1, changeset.num_modified_relations
1505 assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
1506 assert_equal [new_node_id, node.id], Way.find(way.id).nds, "way nodes should match"
1507 Relation.find(relation.id).members.each do |type, id, _role|
1508 assert_equal new_node_id, id, "relation should contain new node" if type == "node"
1513 # test that a placeholder can be reused within the same upload.
1514 def test_upload_create_modify_delete_node_reusing_placeholder
1515 changeset = create(:changeset)
1520 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1521 <tag k="foo" v="bar"/>
1525 <node id='-1' lon='1' lat='1' changeset='#{changeset.id}' version='1'/>
1528 <node id='-1' lon='2' lat='2' changeset='#{changeset.id}' version='2'/>
1533 auth_header = bearer_authorization_header changeset.user
1535 assert_difference "Node.count", 1 do
1536 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1538 assert_response :success
1541 assert_dom "diffResult>node", 3
1542 assert_dom "diffResult>node[old_id='-1']", 3
1545 assert_equal 3, changeset.num_changes
1546 assert_predicate changeset, :num_type_changes_in_sync?
1547 assert_equal 1, changeset.num_created_nodes
1548 assert_equal 1, changeset.num_modified_nodes
1549 assert_equal 1, changeset.num_deleted_nodes
1552 assert_equal 3, node.version
1553 assert_not node.visible
1556 def test_upload_create_and_duplicate_delete
1557 changeset = create(:changeset)
1562 <node id="-1" lat="39" lon="116" changeset="#{changeset.id}" />
1565 <node id="-1" version="1" changeset="#{changeset.id}" />
1566 <node id="-1" version="1" changeset="#{changeset.id}" />
1571 auth_header = bearer_authorization_header changeset.user
1573 assert_no_difference "Node.count" do
1574 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1576 assert_response :gone
1579 assert_no_changes_in changeset
1582 def test_upload_create_and_duplicate_delete_if_unused
1583 changeset = create(:changeset)
1588 <node id="-1" lat="39" lon="116" changeset="#{changeset.id}" />
1590 <delete if-unused="true">
1591 <node id="-1" version="1" changeset="#{changeset.id}" />
1592 <node id="-1" version="1" changeset="#{changeset.id}" />
1597 auth_header = bearer_authorization_header changeset.user
1599 assert_difference "Node.count", 1 do
1600 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1602 assert_response :success
1605 assert_dom "diffResult>node", 3
1606 assert_dom "diffResult>node[old_id='-1']", 3
1607 assert_dom "diffResult>node[new_version='1']", 1
1608 assert_dom "diffResult>node[new_version='2']", 1
1611 assert_equal 2, changeset.num_changes
1612 assert_predicate changeset, :num_type_changes_in_sync?
1613 assert_equal 1, changeset.num_created_nodes
1614 assert_equal 1, changeset.num_deleted_nodes
1617 assert_equal 2, node.version
1618 assert_not node.visible
1621 # -------------------------------------
1622 # Test bounding boxes.
1623 # -------------------------------------
1625 def test_upload_bbox_of_widely_spaced_nodes
1626 user = create(:user)
1628 # create an old changeset to ensure we have the maximum rate limit
1629 create(:changeset, :user => user, :created_at => Time.now.utc - 28.days)
1631 changeset = create(:changeset, :user => user)
1633 # upload some widely-spaced nodes, spiralling positive and negative
1637 <node id='-1' lon='-20' lat='-10' changeset='#{changeset.id}'/>
1638 <node id='-10' lon='20' lat='10' changeset='#{changeset.id}'/>
1639 <node id='-2' lon='-40' lat='-20' changeset='#{changeset.id}'/>
1640 <node id='-11' lon='40' lat='20' changeset='#{changeset.id}'/>
1641 <node id='-3' lon='-60' lat='-30' changeset='#{changeset.id}'/>
1642 <node id='-12' lon='60' lat='30' changeset='#{changeset.id}'/>
1643 <node id='-4' lon='-80' lat='-40' changeset='#{changeset.id}'/>
1644 <node id='-13' lon='80' lat='40' changeset='#{changeset.id}'/>
1645 <node id='-5' lon='-100' lat='-50' changeset='#{changeset.id}'/>
1646 <node id='-14' lon='100' lat='50' changeset='#{changeset.id}'/>
1647 <node id='-6' lon='-120' lat='-60' changeset='#{changeset.id}'/>
1648 <node id='-15' lon='120' lat='60' changeset='#{changeset.id}'/>
1649 <node id='-7' lon='-140' lat='-70' changeset='#{changeset.id}'/>
1650 <node id='-16' lon='140' lat='70' changeset='#{changeset.id}'/>
1651 <node id='-8' lon='-160' lat='-80' changeset='#{changeset.id}'/>
1652 <node id='-17' lon='160' lat='80' changeset='#{changeset.id}'/>
1653 <node id='-9' lon='-179.9' lat='-89.9' changeset='#{changeset.id}'/>
1654 <node id='-18' lon='179.9' lat='89.9' changeset='#{changeset.id}'/>
1659 auth_header = bearer_authorization_header user
1661 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1663 assert_response :success
1666 assert_equal 18, changeset.num_changes
1667 assert_predicate changeset, :num_type_changes_in_sync?
1668 assert_equal 18, changeset.num_created_nodes
1670 # check that the changeset bbox is within bounds
1671 assert_operator changeset.min_lon, :>=, -180 * GeoRecord::SCALE, "Minimum longitude (#{changeset.min_lon / GeoRecord::SCALE}) should be >= -180 to be valid."
1672 assert_operator changeset.max_lon, :<=, 180 * GeoRecord::SCALE, "Maximum longitude (#{changeset.max_lon / GeoRecord::SCALE}) should be <= 180 to be valid."
1673 assert_operator changeset.min_lat, :>=, -90 * GeoRecord::SCALE, "Minimum latitude (#{changeset.min_lat / GeoRecord::SCALE}) should be >= -90 to be valid."
1674 assert_operator changeset.max_lat, :<=, 90 * GeoRecord::SCALE, "Maximum latitude (#{changeset.max_lat / GeoRecord::SCALE}) should be <= 90 to be valid."
1677 def test_upload_bbox_of_moved_node
1678 changeset = create(:changeset)
1679 node = create(:node, :lat => 1.0, :lon => 2.0)
1684 <node id='#{node.id}' lat='1.1' lon='2.1' changeset='#{changeset.id}' version='1'/>
1689 auth_header = bearer_authorization_header changeset.user
1691 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1693 assert_response :success
1696 assert_equal 1, changeset.num_changes
1697 assert_predicate changeset, :num_type_changes_in_sync?
1698 assert_equal 1, changeset.num_modified_nodes
1701 assert_equal 1.0 * GeoRecord::SCALE, changeset.min_lat, "min_lat should be 1.0 degrees"
1702 assert_equal 2.0 * GeoRecord::SCALE, changeset.min_lon, "min_lon should be 2.0 degrees"
1703 assert_equal 1.1 * GeoRecord::SCALE, changeset.max_lat, "max_lat should be 1.1 degrees"
1704 assert_equal 2.1 * GeoRecord::SCALE, changeset.max_lon, "max_lon should be 2.1 degrees"
1707 def test_upload_bbox_of_extended_way
1709 initial_node = create(:node, :lat => 1.1, :lon => 2.1)
1710 create(:way_node, :way => way, :node => initial_node)
1711 added_node = create(:node, :lat => 1.3, :lon => 2.3)
1712 changeset = create(:changeset)
1717 <way id='#{way.id}' changeset='#{changeset.id}' version='1'>
1718 <nd ref='#{initial_node.id}'/>
1719 <nd ref='#{added_node.id}'/>
1725 auth_header = bearer_authorization_header changeset.user
1727 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1729 assert_response :success
1732 assert_equal 1, changeset.num_changes
1733 assert_predicate changeset, :num_type_changes_in_sync?
1734 assert_equal 1, changeset.num_modified_ways
1737 assert_equal 1.1 * GeoRecord::SCALE, changeset.min_lat, "min_lat should be 1.1 degrees"
1738 assert_equal 2.1 * GeoRecord::SCALE, changeset.min_lon, "min_lon should be 2.1 degrees"
1739 assert_equal 1.3 * GeoRecord::SCALE, changeset.max_lat, "max_lat should be 1.3 degrees"
1740 assert_equal 2.3 * GeoRecord::SCALE, changeset.max_lon, "max_lon should be 2.3 degrees"
1743 # -------------------------------------
1744 # Test upload rate/size limits.
1745 # -------------------------------------
1747 def test_upload_initial_rate_limit
1748 user = create(:user)
1749 node = create(:node)
1750 way = create(:way_with_nodes, :nodes_count => 2)
1751 relation = create(:relation)
1753 # create a changeset that puts us near the initial rate limit
1754 num_changes = Settings.initial_changes_per_hour - 2
1755 changeset = create(:changeset, :user => user,
1756 :created_at => Time.now.utc - 5.minutes,
1757 :num_changes => num_changes,
1758 :num_created_nodes => num_changes)
1763 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1764 <tag k='foo' v='bar'/>
1765 <tag k='baz' v='bat'/>
1767 <way id='-1' changeset='#{changeset.id}'>
1768 <nd ref='#{node.id}'/>
1772 <relation id='-1' changeset='#{changeset.id}'>
1773 <member type='way' role='some' ref='#{way.id}'/>
1774 <member type='node' role='some' ref='#{node.id}'/>
1775 <member type='relation' role='some' ref='#{relation.id}'/>
1781 auth_header = bearer_authorization_header user
1783 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1785 assert_response :too_many_requests, "upload did not hit rate limit"
1788 assert_equal num_changes, changeset.num_changes
1789 assert_predicate changeset, :num_type_changes_in_sync?
1792 def test_upload_maximum_rate_limit
1793 user = create(:user)
1794 node = create(:node)
1795 way = create(:way_with_nodes, :nodes_count => 2)
1796 relation = create(:relation)
1798 # create a changeset to establish our initial edit time
1799 changeset = create(:changeset, :user => user,
1800 :created_at => Time.now.utc - 28.days)
1802 # create changeset to put us near the maximum rate limit
1803 remaining_num_changes = Settings.max_changes_per_hour - 2
1805 while remaining_num_changes.positive?
1806 num_changes = [remaining_num_changes, Changeset::MAX_ELEMENTS].min
1807 changeset = create(:changeset, :user => user,
1808 :created_at => Time.now.utc - 5.minutes,
1809 :num_changes => num_changes,
1810 :num_created_nodes => num_changes)
1811 remaining_num_changes -= num_changes
1817 <node id='-1' lon='0' lat='0' changeset='#{changeset.id}'>
1818 <tag k='foo' v='bar'/>
1819 <tag k='baz' v='bat'/>
1821 <way id='-1' changeset='#{changeset.id}'>
1822 <nd ref='#{node.id}'/>
1826 <relation id='-1' changeset='#{changeset.id}'>
1827 <member type='way' role='some' ref='#{way.id}'/>
1828 <member type='node' role='some' ref='#{node.id}'/>
1829 <member type='relation' role='some' ref='#{relation.id}'/>
1835 auth_header = bearer_authorization_header user
1837 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1839 assert_response :too_many_requests, "upload did not hit rate limit"
1842 assert_equal num_changes, changeset.num_changes
1843 assert_predicate changeset, :num_type_changes_in_sync?
1846 def test_upload_initial_size_limit
1847 user = create(:user)
1849 # create a changeset that puts us near the initial size limit
1850 changeset = create(:changeset, :user => user,
1851 :min_lat => (-0.5 * GeoRecord::SCALE).round, :min_lon => (0.5 * GeoRecord::SCALE).round,
1852 :max_lat => (0.5 * GeoRecord::SCALE).round, :max_lon => (2.5 * GeoRecord::SCALE).round)
1857 <node id='-1' lon='0.9' lat='2.9' changeset='#{changeset.id}'>
1858 <tag k='foo' v='bar'/>
1859 <tag k='baz' v='bat'/>
1865 auth_header = bearer_authorization_header user
1867 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1869 assert_response :payload_too_large, "upload did not hit size limit"
1871 assert_no_changes_in changeset
1874 def test_upload_size_limit_after_one_week
1875 user = create(:user)
1877 # create a changeset to establish our initial edit time
1878 create(:changeset, :user => user, :created_at => Time.now.utc - 7.days)
1880 # create a changeset that puts us near the initial size limit
1881 changeset = create(:changeset, :user => user, :bbox => [0.5, -0.5, 2.5, 0.5])
1886 <node id='-1' lon='35' lat='35' changeset='#{changeset.id}'>
1887 <tag k='foo' v='bar'/>
1888 <tag k='baz' v='bat'/>
1894 auth_header = bearer_authorization_header user
1896 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1898 assert_response :payload_too_large, "upload did not hit size limit"
1900 assert_no_changes_in changeset
1905 def check_upload_results_in_not_found(&)
1906 changeset = create(:changeset)
1907 diff = "<osmChange>#{yield changeset}</osmChange>"
1908 auth_header = bearer_authorization_header changeset.user
1910 post api_changeset_upload_path(changeset), :params => diff, :headers => auth_header
1912 assert_response :not_found
1914 assert_no_changes_in changeset
1917 def assert_no_changes_in(changeset)
1919 assert_equal 0, changeset.num_changes
1920 assert_predicate changeset, :num_type_changes_in_sync?