1 # frozen_string_literal: true
 
   4 require_relative "elements_test_helper"
 
   7   class RelationsControllerTest < ActionDispatch::IntegrationTest
 
   8     include ElementsTestHelper
 
  11     # test all routes which lead to this controller
 
  14         { :path => "/api/0.6/relations", :method => :get },
 
  15         { :controller => "api/relations", :action => "index" }
 
  18         { :path => "/api/0.6/relations.json", :method => :get },
 
  19         { :controller => "api/relations", :action => "index", :format => "json" }
 
  22         { :path => "/api/0.6/relations", :method => :post },
 
  23         { :controller => "api/relations", :action => "create" }
 
  26         { :path => "/api/0.6/relation/1", :method => :get },
 
  27         { :controller => "api/relations", :action => "show", :id => "1" }
 
  30         { :path => "/api/0.6/relation/1.json", :method => :get },
 
  31         { :controller => "api/relations", :action => "show", :id => "1", :format => "json" }
 
  34         { :path => "/api/0.6/relation/1/full", :method => :get },
 
  35         { :controller => "api/relations", :action => "show", :full => true, :id => "1" }
 
  38         { :path => "/api/0.6/relation/1/full.json", :method => :get },
 
  39         { :controller => "api/relations", :action => "show", :full => true, :id => "1", :format => "json" }
 
  42         { :path => "/api/0.6/relation/1", :method => :put },
 
  43         { :controller => "api/relations", :action => "update", :id => "1" }
 
  46         { :path => "/api/0.6/relation/1", :method => :delete },
 
  47         { :controller => "api/relations", :action => "destroy", :id => "1" }
 
  51         { :controller => "api/relations", :action => "create" },
 
  52         { :path => "/api/0.6/relation/create", :method => :put }
 
  57     # test fetching multiple relations
 
  59       relation1 = create(:relation)
 
  60       relation2 = create(:relation, :deleted)
 
  61       relation3 = create(:relation, :with_history, :version => 2)
 
  62       relation4 = create(:relation, :with_history, :version => 2)
 
  63       relation4.old_relations.find_by(:version => 1).redact!(create(:redaction))
 
  65       # check error when no parameter provided
 
  66       get api_relations_path
 
  67       assert_response :bad_request
 
  69       # check error when no parameter value provided
 
  70       get api_relations_path(:relations => "")
 
  71       assert_response :bad_request
 
  74       get api_relations_path(:relations => "#{relation1.id},#{relation2.id},#{relation3.id},#{relation4.id}")
 
  75       assert_response :success
 
  76       assert_select "osm" do
 
  77         assert_select "relation", :count => 4
 
  78         assert_select "relation[id='#{relation1.id}'][visible='true']", :count => 1
 
  79         assert_select "relation[id='#{relation2.id}'][visible='false']", :count => 1
 
  80         assert_select "relation[id='#{relation3.id}'][visible='true']", :count => 1
 
  81         assert_select "relation[id='#{relation4.id}'][visible='true']", :count => 1
 
  84       # test a working call with json format
 
  85       get api_relations_path(:relations => "#{relation1.id},#{relation2.id},#{relation3.id},#{relation4.id}", :format => "json")
 
  87       js = ActiveSupport::JSON.decode(@response.body)
 
  89       assert_equal 4, js["elements"].count
 
  90       assert_equal(4, js["elements"].count { |a| a["type"] == "relation" })
 
  91       assert_equal(1, js["elements"].count { |a| a["id"] == relation1.id && a["visible"].nil? })
 
  92       assert_equal(1, js["elements"].count { |a| a["id"] == relation2.id && a["visible"] == false })
 
  93       assert_equal(1, js["elements"].count { |a| a["id"] == relation3.id && a["visible"].nil? })
 
  94       assert_equal(1, js["elements"].count { |a| a["id"] == relation4.id && a["visible"].nil? })
 
  96       # check error when a non-existent relation is included
 
  97       get api_relations_path(:relations => "#{relation1.id},#{relation2.id},#{relation3.id},#{relation4.id},0")
 
  98       assert_response :not_found
 
 101     # -------------------------------------
 
 102     # Test showing relations.
 
 103     # -------------------------------------
 
 105     def test_show_not_found
 
 106       get api_relation_path(0)
 
 107       assert_response :not_found
 
 110     def test_show_deleted
 
 111       get api_relation_path(create(:relation, :deleted))
 
 112       assert_response :gone
 
 116       relation = create(:relation, :timestamp => "2021-02-03T00:00:00Z")
 
 117       node = create(:node, :timestamp => "2021-04-05T00:00:00Z")
 
 118       create(:relation_member, :relation => relation, :member => node)
 
 120       get api_relation_path(relation)
 
 122       assert_response :success
 
 123       assert_not_nil @response.header["Last-Modified"]
 
 124       assert_equal "2021-02-03T00:00:00Z", Time.parse(@response.header["Last-Modified"]).utc.xmlschema
 
 125       assert_dom "node", :count => 0
 
 126       assert_dom "relation", :count => 1 do
 
 127         assert_dom "> @id", :text => relation.id.to_s
 
 131     def test_full_not_found
 
 132       get api_relation_path(999999, :full => true)
 
 133       assert_response :not_found
 
 136     def test_full_deleted
 
 137       get api_relation_path(create(:relation, :deleted), :full => true)
 
 138       assert_response :gone
 
 142       relation = create(:relation)
 
 144       get api_relation_path(relation, :full => true)
 
 146       assert_response :success
 
 147       assert_dom "relation", :count => 1 do
 
 148         assert_dom "> @id", :text => relation.id.to_s
 
 152     def test_full_with_node_member
 
 153       relation = create(:relation)
 
 155       create(:relation_member, :relation => relation, :member => node)
 
 157       get api_relation_path(relation, :full => true)
 
 159       assert_response :success
 
 160       assert_dom "node", :count => 1 do
 
 161         assert_dom "> @id", :text => node.id.to_s
 
 163       assert_dom "relation", :count => 1 do
 
 164         assert_dom "> @id", :text => relation.id.to_s
 
 168     def test_full_with_way_member
 
 169       relation = create(:relation)
 
 170       way = create(:way_with_nodes)
 
 171       create(:relation_member, :relation => relation, :member => way)
 
 173       get api_relation_path(relation, :full => true)
 
 175       assert_response :success
 
 176       assert_dom "node", :count => 1 do
 
 177         assert_dom "> @id", :text => way.nodes[0].id.to_s
 
 179       assert_dom "way", :count => 1 do
 
 180         assert_dom "> @id", :text => way.id.to_s
 
 182       assert_dom "relation", :count => 1 do
 
 183         assert_dom "> @id", :text => relation.id.to_s
 
 187     def test_full_with_node_member_json
 
 188       relation = create(:relation)
 
 190       create(:relation_member, :relation => relation, :member => node)
 
 192       get api_relation_path(relation, :full => true, :format => "json")
 
 194       assert_response :success
 
 195       js = ActiveSupport::JSON.decode(@response.body)
 
 197       assert_equal 2, js["elements"].count
 
 199       js_relations = js["elements"].filter { |e| e["type"] == "relation" }
 
 200       assert_equal 1, js_relations.count
 
 201       assert_equal relation.id, js_relations[0]["id"]
 
 202       assert_equal 1, js_relations[0]["members"].count
 
 203       assert_equal "node", js_relations[0]["members"][0]["type"]
 
 204       assert_equal node.id, js_relations[0]["members"][0]["ref"]
 
 206       js_nodes = js["elements"].filter { |e| e["type"] == "node" }
 
 207       assert_equal 1, js_nodes.count
 
 208       assert_equal node.id, js_nodes[0]["id"]
 
 211     # -------------------------------------
 
 212     # Test creating relations.
 
 213     # -------------------------------------
 
 215     def test_create_without_members_by_private_user
 
 216       with_unchanging_request([:data_public => false]) do |headers, changeset|
 
 219             <relation changeset='#{changeset.id}'>
 
 220               <tag k='test' v='yes' />
 
 225         post api_relations_path, :params => osm, :headers => headers
 
 227         assert_response :forbidden, "relation upload should have failed with forbidden"
 
 231     def test_create_with_node_member_with_role_by_private_user
 
 234       with_unchanging_request([:data_public => false]) do |headers, changeset|
 
 237             <relation changeset='#{changeset.id}'>
 
 238               <member ref='#{node.id}' type='node' role='some'/>
 
 239               <tag k='test' v='yes' />
 
 244         post api_relations_path, :params => osm, :headers => headers
 
 246         assert_response :forbidden, "relation upload did not return forbidden status"
 
 250     def test_create_with_node_member_without_role_by_private_user
 
 253       with_unchanging_request([:data_public => false]) do |headers, changeset|
 
 256             <relation changeset='#{changeset.id}'>
 
 257               <member ref='#{node.id}' type='node'/>
 
 258               <tag k='test' v='yes' />
 
 263         post api_relations_path, :params => osm, :headers => headers
 
 265         assert_response :forbidden, "relation upload did not return forbidden status"
 
 269     def test_create_with_node_and_way_members_by_private_user
 
 271       way = create(:way_with_nodes, :nodes_count => 2)
 
 273       with_unchanging_request([:data_public => false]) do |headers, changeset|
 
 276             <relation changeset='#{changeset.id}'>
 
 277               <member type='node' ref='#{node.id}' role='some'/>
 
 278               <member type='way' ref='#{way.id}' role='other'/>
 
 279               <tag k='test' v='yes' />
 
 284         post api_relations_path, :params => osm, :headers => headers
 
 286         assert_response :forbidden, "relation upload did not return success status"
 
 290     def test_create_without_members
 
 291       with_request do |headers, changeset|
 
 292         assert_difference "Relation.count" => 1,
 
 293                           "RelationMember.count" => 0 do
 
 296               <relation changeset='#{changeset.id}'>
 
 297                 <tag k='test' v='yes' />
 
 302           post api_relations_path, :params => osm, :headers => headers
 
 304           assert_response :success, "relation upload did not return success status"
 
 307         created_relation_id = @response.body
 
 308         relation = Relation.find(created_relation_id)
 
 309         assert_empty relation.members
 
 310         assert_equal({ "test" => "yes" }, relation.tags)
 
 311         assert_equal changeset.id, relation.changeset_id, "saved relation does not belong in the changeset it was assigned to"
 
 312         assert relation.visible, "saved relation is not visible"
 
 315         assert_equal 1, changeset.num_changes
 
 316         assert_predicate changeset, :num_type_changes_in_sync?
 
 317         assert_equal 1, changeset.num_created_relations
 
 321     def test_create_with_node_member_with_role
 
 324       with_request do |headers, changeset|
 
 325         assert_difference "Relation.count" => 1,
 
 326                           "RelationMember.count" => 1 do
 
 329               <relation changeset='#{changeset.id}'>
 
 330                 <member ref='#{node.id}' type='node' role='some'/>
 
 331                 <tag k='test' v='yes' />
 
 336           post api_relations_path, :params => osm, :headers => headers
 
 338           assert_response :success, "relation upload did not return success status"
 
 341         created_relation_id = @response.body
 
 342         relation = Relation.find(created_relation_id)
 
 343         assert_equal [["Node", node.id, "some"]], relation.members
 
 344         assert_equal({ "test" => "yes" }, relation.tags)
 
 345         assert_equal changeset.id, relation.changeset_id, "saved relation does not belong in the changeset it was assigned to"
 
 346         assert relation.visible, "saved relation is not visible"
 
 349         assert_equal 1, changeset.num_changes
 
 350         assert_predicate changeset, :num_type_changes_in_sync?
 
 351         assert_equal 1, changeset.num_created_relations
 
 355     def test_create_with_node_member_without_role
 
 358       with_request do |headers, changeset|
 
 359         assert_difference "Relation.count" => 1,
 
 360                           "RelationMember.count" => 1 do
 
 363               <relation changeset='#{changeset.id}'>
 
 364                 <member ref='#{node.id}' type='node'/>
 
 365                 <tag k='test' v='yes' />
 
 370           post api_relations_path, :params => osm, :headers => headers
 
 372           assert_response :success, "relation upload did not return success status"
 
 375         created_relation_id = @response.body
 
 376         relation = Relation.find(created_relation_id)
 
 377         assert_equal [["Node", node.id, ""]], relation.members
 
 378         assert_equal({ "test" => "yes" }, relation.tags)
 
 379         assert_equal changeset.id, relation.changeset_id, "saved relation does not belong in the changeset it was assigned to"
 
 380         assert relation.visible, "saved relation is not visible"
 
 383         assert_equal 1, changeset.num_changes
 
 384         assert_predicate changeset, :num_type_changes_in_sync?
 
 385         assert_equal 1, changeset.num_created_relations
 
 389     def test_create_with_node_and_way_members
 
 391       way = create(:way_with_nodes, :nodes_count => 2)
 
 393       with_request do |headers, changeset|
 
 394         assert_difference "Relation.count" => 1,
 
 395                           "RelationMember.count" => 2 do
 
 398               <relation changeset='#{changeset.id}'>
 
 399                 <member type='node' ref='#{node.id}' role='some'/>
 
 400                 <member type='way' ref='#{way.id}' role='other'/>
 
 401                 <tag k='test' v='yes' />
 
 406           post api_relations_path, :params => osm, :headers => headers
 
 408           assert_response :success, "relation upload did not return success status"
 
 411         created_relation_id = @response.body
 
 412         relation = Relation.find(created_relation_id)
 
 413         assert_equal [["Node", node.id, "some"],
 
 414                       ["Way", way.id, "other"]], relation.members
 
 415         assert_equal({ "test" => "yes" }, relation.tags)
 
 416         assert_equal changeset.id, relation.changeset_id, "saved relation does not belong in the changeset it was assigned to"
 
 417         assert relation.visible, "saved relation is not visible"
 
 420         assert_equal 1, changeset.num_changes
 
 421         assert_predicate changeset, :num_type_changes_in_sync?
 
 422         assert_equal 1, changeset.num_created_relations
 
 426     def test_create_in_missing_changeset
 
 429       with_unchanging_request do |headers|
 
 432             <relation changeset='0'>
 
 433               <member type='node' ref='#{node.id}' role='some'/>
 
 438         post api_relations_path, :params => osm, :headers => headers
 
 440         assert_response :conflict
 
 444     def test_create_with_missing_node_member
 
 445       with_unchanging_request do |headers, changeset|
 
 448             <relation changeset='#{changeset.id}'>
 
 449               <member type='node' ref='0'/>
 
 454         post api_relations_path, :params => osm, :headers => headers
 
 456         assert_response :precondition_failed, "relation upload with invalid node did not return 'precondition failed'"
 
 457         assert_equal "Precondition failed: Relation with id  cannot be saved due to Node with id 0", @response.body
 
 461     def test_create_with_invalid_member_type
 
 464       with_unchanging_request do |headers, changeset|
 
 467             <relation changeset='#{changeset.id}'>
 
 468               <member type='type' ref='#{node.id}' role=''/>
 
 473         post api_relations_path, :params => osm, :headers => headers
 
 475         assert_response :bad_request
 
 476         assert_match(/Cannot parse valid relation from xml string/, @response.body)
 
 477         assert_match(/The type is not allowed only, /, @response.body)
 
 481     def test_create_and_show
 
 483       changeset = create(:changeset, :user => user)
 
 487           <relation changeset='#{changeset.id}'/>
 
 491       post api_relations_path, :params => osm, :headers => bearer_authorization_header(user)
 
 493       assert_response :success, "relation upload did not return success status"
 
 495       created_relation_id = @response.body
 
 497       get api_relation_path(created_relation_id)
 
 499       assert_response :success
 
 502     def test_create_race_condition
 
 504       changeset = create(:changeset, :user => user)
 
 506       auth_header = bearer_authorization_header user
 
 507       path = api_relations_path
 
 508       concurrency_level = 16
 
 510       threads = Array.new(concurrency_level) do
 
 514               <relation changeset='#{changeset.id}'>
 
 515                 <member type='node' ref='#{node.id}' role=''/>
 
 519           post path, :params => osm, :headers => auth_header
 
 525       assert_equal concurrency_level, changeset.num_changes
 
 526       assert_predicate changeset, :num_type_changes_in_sync?
 
 527       assert_equal concurrency_level, changeset.num_created_relations
 
 530     # ------------------------------------
 
 531     # Test updating relations
 
 532     # ------------------------------------
 
 535       relation = create(:relation)
 
 537       with_request do |headers, changeset|
 
 538         osm_xml = xml_for_relation relation
 
 539         osm_xml = update_changeset osm_xml, changeset.id
 
 541         put api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 543         assert_response :success
 
 546         assert_equal 2, relation.version
 
 549         assert_equal 1, changeset.num_changes
 
 550         assert_predicate changeset, :num_type_changes_in_sync?
 
 551         assert_equal 1, changeset.num_modified_relations
 
 555     def test_update_in_missing_changeset
 
 556       with_unchanging(:relation) do |relation|
 
 557         with_unchanging_request do |headers|
 
 558           osm_xml = xml_for_relation relation
 
 559           osm_xml = update_changeset osm_xml, 0
 
 561           put api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 563           assert_response :conflict, "update with changeset=0 should be rejected"
 
 568     def test_update_other_relation
 
 569       with_unchanging(:relation) do |relation|
 
 570         with_unchanging(:relation) do |other_relation|
 
 571           with_unchanging_request do |headers, changeset|
 
 572             osm_xml = xml_for_relation other_relation
 
 573             osm_xml = update_changeset osm_xml, changeset.id
 
 575             put api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 577             assert_response :bad_request
 
 583     # -------------------------------------
 
 584     # Test deleting relations.
 
 585     # -------------------------------------
 
 587     def test_destroy_when_unauthorized
 
 588       with_unchanging(:relation) do |relation|
 
 589         delete api_relation_path(relation)
 
 591         assert_response :unauthorized
 
 595     def test_destroy_without_payload_by_private_user
 
 596       with_unchanging(:relation) do |relation|
 
 597         with_unchanging_request([:data_public => false]) do |headers|
 
 598           delete api_relation_path(relation), :headers => headers
 
 600           assert_response :forbidden
 
 605     def test_destroy_without_changeset_id_by_private_user
 
 606       with_unchanging(:relation) do |relation|
 
 607         with_unchanging_request([:data_public => false]) do |headers|
 
 608           osm = "<osm><relation id='#{relation.id}' version='#{relation.version}'/></osm>"
 
 610           delete api_relation_path(relation), :params => osm, :headers => headers
 
 612           assert_response :forbidden
 
 617     def test_destroy_in_closed_changeset_by_private_user
 
 618       with_unchanging(:relation) do |relation|
 
 619         with_unchanging_request([:data_public => false], [:closed]) do |headers, changeset|
 
 620           osm_xml = xml_for_relation relation
 
 621           osm_xml = update_changeset osm_xml, changeset.id
 
 623           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 625           assert_response :forbidden
 
 630     def test_destroy_in_missing_changeset_by_private_user
 
 631       with_unchanging(:relation) do |relation|
 
 632         with_unchanging_request([:data_public => false]) do |headers|
 
 633           osm_xml = xml_for_relation relation
 
 634           osm_xml = update_changeset osm_xml, 0
 
 636           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 638           assert_response :forbidden
 
 643     def test_destroy_relation_used_by_other_relation_by_private_user
 
 644       with_unchanging(:relation) do |relation|
 
 645         create(:relation_member, :member => relation)
 
 647         with_unchanging_request([:data_public => false]) do |headers, changeset|
 
 648           osm_xml = xml_for_relation relation
 
 649           osm_xml = update_changeset osm_xml, changeset.id
 
 651           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 653           assert_response :forbidden
 
 658     def test_destroy_by_private_user
 
 659       with_unchanging(:relation) do |relation|
 
 660         with_unchanging_request([:data_public => false]) do |headers, changeset|
 
 661           osm_xml = xml_for_relation relation
 
 662           osm_xml = update_changeset osm_xml, changeset.id
 
 664           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 666           assert_response :forbidden
 
 671     def test_destroy_deleted_relation_by_private_user
 
 672       with_unchanging(:relation, :deleted) do |relation|
 
 673         with_unchanging_request([:data_public => false]) do |headers, changeset|
 
 674           osm_xml = xml_for_relation relation
 
 675           osm_xml = update_changeset osm_xml, changeset.id
 
 677           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 679           assert_response :forbidden
 
 684     def test_destroy_missing_relation_by_private_user
 
 685       with_unchanging_request([:data_public => false]) do |headers|
 
 686         delete api_relation_path(0), :headers => headers
 
 688         assert_response :forbidden
 
 692     def test_destroy_without_payload
 
 693       with_unchanging(:relation) do |relation|
 
 694         with_unchanging_request do |headers|
 
 695           delete api_relation_path(relation), :headers => headers
 
 697           assert_response :bad_request
 
 702     def test_destroy_without_changeset_id
 
 703       with_unchanging(:relation) do |relation|
 
 704         with_unchanging_request do |headers|
 
 705           osm = "<osm><relation id='#{relation.id}' version='#{relation.version}'/></osm>"
 
 707           delete api_relation_path(relation), :params => osm, :headers => headers
 
 709           assert_response :bad_request
 
 710           assert_match(/Changeset id is missing/, @response.body)
 
 715     def test_destroy_in_closed_changeset
 
 716       with_unchanging(:relation) do |relation|
 
 717         with_unchanging_request([], [:closed]) do |headers, changeset|
 
 718           osm_xml = xml_for_relation relation
 
 719           osm_xml = update_changeset osm_xml, changeset.id
 
 721           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 723           assert_response :conflict
 
 728     def test_destroy_in_missing_changeset
 
 729       with_unchanging(:relation) do |relation|
 
 730         with_unchanging_request do |headers|
 
 731           osm_xml = xml_for_relation relation
 
 732           osm_xml = update_changeset osm_xml, 0
 
 734           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 736           assert_response :conflict
 
 741     def test_destroy_in_changeset_of_other_user
 
 742       with_unchanging(:relation) do |relation|
 
 743         other_user = create(:user)
 
 745         with_unchanging_request([], [:user => other_user]) do |headers, changeset|
 
 746           osm_xml = xml_for_relation relation
 
 747           osm_xml = update_changeset osm_xml, changeset.id
 
 749           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 751           assert_response :conflict, "shouldn't be able to delete a relation in a changeset owned by someone else (#{@response.body})"
 
 756     def test_destroy_other_relation
 
 757       with_unchanging(:relation) do |relation|
 
 758         with_unchanging(:relation) do |other_relation|
 
 759           with_unchanging_request do |headers, changeset|
 
 760             osm_xml = xml_for_relation other_relation
 
 761             osm_xml = update_changeset osm_xml, changeset.id
 
 763             delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 765             assert_response :bad_request, "shouldn't be able to delete a relation when payload is different to the url"
 
 771     def test_destroy_relation_used_by_other_relation
 
 772       with_unchanging(:relation) do |relation|
 
 773         super_relation = create(:relation)
 
 774         create(:relation_member, :relation => super_relation, :member => relation)
 
 776         with_unchanging_request do |headers, changeset|
 
 777           osm_xml = xml_for_relation relation
 
 778           osm_xml = update_changeset osm_xml, changeset.id
 
 780           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 782           assert_response :precondition_failed, "shouldn't be able to delete a relation used in a relation (#{@response.body})"
 
 783           assert_equal "Precondition failed: The relation #{relation.id} is used in relation #{super_relation.id}.", @response.body
 
 789       relation = create(:relation)
 
 790       create_list(:relation_tag, 4, :relation => relation)
 
 792       with_request do |headers, changeset|
 
 793         osm_xml = xml_for_relation relation
 
 794         osm_xml = update_changeset osm_xml, changeset.id
 
 796         delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 798         assert_response :success
 
 799         assert_operator @response.body.to_i, :>, relation.version, "delete request should return a new version number for relation"
 
 802         assert_equal 1, changeset.num_changes
 
 803         assert_predicate changeset, :num_type_changes_in_sync?
 
 804         assert_equal 1, changeset.num_deleted_relations
 
 808     def test_destroy_deleted_relation
 
 809       with_unchanging(:relation, :deleted) do |relation|
 
 810         with_unchanging_request do |headers, changeset|
 
 811           osm_xml = xml_for_relation relation
 
 812           osm_xml = update_changeset osm_xml, changeset.id
 
 814           delete api_relation_path(relation), :params => osm_xml.to_s, :headers => headers
 
 816           assert_response :gone
 
 821     def test_destroy_super_relation_then_used_relation
 
 822       used_relation = create(:relation)
 
 823       super_relation = create(:relation)
 
 824       create(:relation_member, :relation => super_relation, :member => used_relation)
 
 826       with_request do |headers, changeset|
 
 827         osm_xml = xml_for_relation super_relation
 
 828         osm_xml = update_changeset osm_xml, changeset.id
 
 830         delete api_relation_path(super_relation), :params => osm_xml.to_s, :headers => headers
 
 832         assert_response :success
 
 835       with_request do |headers, changeset|
 
 836         osm_xml = xml_for_relation used_relation
 
 837         osm_xml = update_changeset osm_xml, changeset.id
 
 839         delete api_relation_path(used_relation), :params => osm_xml.to_s, :headers => headers
 
 841         assert_response :success, "should be able to delete a relation used in an old relation (#{@response.body})"
 
 845     def test_destroy_missing_relation
 
 846       with_unchanging_request do |headers|
 
 847         delete api_relation_path(0), :headers => headers
 
 849         assert_response :not_found
 
 854     # test initial rate limit
 
 855     def test_initial_rate_limit
 
 860       node1 = create(:node)
 
 861       node2 = create(:node)
 
 863       # create a changeset that puts us near the initial rate limit
 
 864       changeset = create(:changeset, :user => user,
 
 865                                      :created_at => Time.now.utc - 5.minutes,
 
 866                                      :num_changes => Settings.initial_changes_per_hour - 1)
 
 868       # create authentication header
 
 869       auth_header = bearer_authorization_header user
 
 871       # try creating a relation
 
 874           <relation changeset='#{changeset.id}'>
 
 875             <member ref='#{node1.id}' type='node' role='some'/>
 
 876             <member ref='#{node2.id}' type='node' role='some'/>
 
 880       post api_relations_path, :params => xml, :headers => auth_header
 
 881       assert_response :success, "relation create did not return success status"
 
 883       # get the id of the relation we created
 
 884       relationid = @response.body
 
 886       # try updating the relation, which should be rate limited
 
 889           <relation id='#{relationid}' version='1' changeset='#{changeset.id}'>
 
 890             <member ref='#{node2.id}' type='node' role='some'/>
 
 891             <member ref='#{node1.id}' type='node' role='some'/>
 
 895       put api_relation_path(relationid), :params => xml, :headers => auth_header
 
 896       assert_response :too_many_requests, "relation update did not hit rate limit"
 
 898       # try deleting the relation, which should be rate limited
 
 899       xml = "<osm><relation id='#{relationid}' version='2' changeset='#{changeset.id}'/></osm>"
 
 900       delete api_relation_path(relationid), :params => xml, :headers => auth_header
 
 901       assert_response :too_many_requests, "relation delete did not hit rate limit"
 
 903       # try creating a relation, which should be rate limited
 
 906           <relation changeset='#{changeset.id}'>
 
 907             <member ref='#{node1.id}' type='node' role='some'/>
 
 908             <member ref='#{node2.id}' type='node' role='some'/>
 
 912       post api_relations_path, :params => xml, :headers => auth_header
 
 913       assert_response :too_many_requests, "relation create did not hit rate limit"
 
 917     # test maximum rate limit
 
 918     def test_maximum_rate_limit
 
 923       node1 = create(:node)
 
 924       node2 = create(:node)
 
 926       # create a changeset to establish our initial edit time
 
 927       changeset = create(:changeset, :user => user,
 
 928                                      :created_at => Time.now.utc - 28.days)
 
 930       # create changeset to put us near the maximum rate limit
 
 931       total_changes = Settings.max_changes_per_hour - 1
 
 932       while total_changes.positive?
 
 933         changes = [total_changes, Changeset::MAX_ELEMENTS].min
 
 934         changeset = create(:changeset, :user => user,
 
 935                                        :created_at => Time.now.utc - 5.minutes,
 
 936                                        :num_changes => changes)
 
 937         total_changes -= changes
 
 940       # create authentication header
 
 941       auth_header = bearer_authorization_header user
 
 943       # try creating a relation
 
 946           <relation changeset='#{changeset.id}'>
 
 947             <member ref='#{node1.id}' type='node' role='some'/>
 
 948             <member ref='#{node2.id}' type='node' role='some'/>
 
 952       post api_relations_path, :params => xml, :headers => auth_header
 
 953       assert_response :success, "relation create did not return success status"
 
 955       # get the id of the relation we created
 
 956       relationid = @response.body
 
 958       # try updating the relation, which should be rate limited
 
 961           <relation id='#{relationid}' version='1' changeset='#{changeset.id}'>
 
 962             <member ref='#{node2.id}' type='node' role='some'/>
 
 963             <member ref='#{node1.id}' type='node' role='some'/>
 
 967       put api_relation_path(relationid), :params => xml, :headers => auth_header
 
 968       assert_response :too_many_requests, "relation update did not hit rate limit"
 
 970       # try deleting the relation, which should be rate limited
 
 971       xml = "<osm><relation id='#{relationid}' version='2' changeset='#{changeset.id}'/></osm>"
 
 972       delete api_relation_path(relationid), :params => xml, :headers => auth_header
 
 973       assert_response :too_many_requests, "relation delete did not hit rate limit"
 
 975       # try creating a relation, which should be rate limited
 
 978           <relation changeset='#{changeset.id}'>
 
 979             <member ref='#{node1.id}' type='node' role='some'/>
 
 980             <member ref='#{node2.id}' type='node' role='some'/>
 
 984       post api_relations_path, :params => xml, :headers => auth_header
 
 985       assert_response :too_many_requests, "relation create did not hit rate limit"
 
 991       [Relation, RelationTag, RelationMember,
 
 992        OldRelation, OldRelationTag, OldRelationMember]
 
 996     # update an attribute in the node element
 
 997     def xml_attr_rewrite(xml, name, value)
 
 998       xml.find("//osm/relation").first[name] = value.to_s