1 require File.dirname(__FILE__) + '/../test_helper'
 
   2 require 'changeset_controller'
 
   4 class ChangesetControllerTest < ActionController::TestCase
 
   7   def basic_authorization(user, pass)
 
   8     @request.env["HTTP_AUTHORIZATION"] = "Basic %s" % Base64.encode64("#{user}:#{pass}")
 
  12     @request.env["RAW_POST_DATA"] = c.to_s
 
  15   # -----------------------
 
  16   # Test simple changeset creation
 
  17   # -----------------------
 
  20     basic_authorization "test@openstreetmap.org", "test"
 
  22     # Create the first user's changeset
 
  23     content "<osm><changeset>" +
 
  24       "<tag k='created_by' v='osm test suite checking changesets'/>" + 
 
  28     assert_response :success, "Creation of changeset did not return sucess status"
 
  29     newid = @response.body
 
  32   def test_create_invalid
 
  33     basic_authorization "test@openstreetmap.org", "test"
 
  34     content "<osm><changeset></osm>"
 
  36     assert_response :bad_request, "creating a invalid changeset should fail"
 
  48   # upload something simple, but valid and check that it can 
 
  50   def test_upload_simple_valid
 
  51     basic_authorization "test@openstreetmap.org", "test"
 
  53     # simple diff to change a node, way and relation by removing 
 
  58   <node id='1' lon='0' lat='0' changeset='1' version='1'/>
 
  59   <way id='1' changeset='1' version='1'>
 
  64   <relation id='1' changeset='1' version='1'>
 
  65    <member type='way' role='some' ref='3'/>
 
  66    <member type='node' role='some' ref='5'/>
 
  67    <member type='relation' role='some' ref='3'/>
 
  75     post :upload, :id => 1
 
  76     assert_response :success, 
 
  77       "can't upload a simple valid diff to changeset: #{@response.body}"
 
  79     # check that the changes made it into the database
 
  80     assert_equal 0, Node.find(1).tags.size, "node 1 should now have no tags"
 
  81     assert_equal 0, Way.find(1).tags.size, "way 1 should now have no tags"
 
  82     assert_equal 0, Relation.find(1).tags.size, "relation 1 should now have no tags"
 
  86   # upload something which creates new objects using placeholders
 
  87   def test_upload_create_valid
 
  88     basic_authorization "test@openstreetmap.org", "test"
 
  90     # simple diff to create a node way and relation using placeholders
 
  94   <node id='-1' lon='0' lat='0' changeset='1'>
 
  95    <tag k='foo' v='bar'/>
 
  96    <tag k='baz' v='bat'/>
 
  98   <way id='-1' changeset='1'>
 
 103   <relation id='-1' changeset='1'>
 
 104    <member type='way' role='some' ref='3'/>
 
 105    <member type='node' role='some' ref='5'/>
 
 106    <member type='relation' role='some' ref='3'/>
 
 114     post :upload, :id => 1
 
 115     assert_response :success, 
 
 116       "can't upload a simple valid creation to changeset: #{@response.body}"
 
 118     # check the returned payload
 
 119     assert_select "osm[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
 
 120     assert_select "osm>node", 1
 
 121     assert_select "osm>way", 1
 
 122     assert_select "osm>relation", 1
 
 124     # inspect the response to find out what the new element IDs are
 
 125     doc = XML::Parser.string(@response.body).parse
 
 126     new_node_id = doc.find("//osm/node").first["new_id"].to_i
 
 127     new_way_id = doc.find("//osm/way").first["new_id"].to_i
 
 128     new_rel_id = doc.find("//osm/relation").first["new_id"].to_i
 
 130     # check the old IDs are all present and negative one
 
 131     assert_equal -1, doc.find("//osm/node").first["old_id"].to_i
 
 132     assert_equal -1, doc.find("//osm/way").first["old_id"].to_i
 
 133     assert_equal -1, doc.find("//osm/relation").first["old_id"].to_i
 
 135     # check the versions are present and equal one
 
 136     assert_equal 1, doc.find("//osm/node").first["new_version"].to_i
 
 137     assert_equal 1, doc.find("//osm/way").first["new_version"].to_i
 
 138     assert_equal 1, doc.find("//osm/relation").first["new_version"].to_i
 
 140     # check that the changes made it into the database
 
 141     assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
 
 142     assert_equal 0, Way.find(new_way_id).tags.size, "new way should have no tags"
 
 143     assert_equal 0, Relation.find(new_rel_id).tags.size, "new relation should have no tags"
 
 147   # test a complex delete where we delete elements which rely on eachother
 
 148   # in the same transaction.
 
 149   def test_upload_delete
 
 150     basic_authorization "test@openstreetmap.org", "test"
 
 152     diff = XML::Document.new
 
 153     diff.root = XML::Node.new "osmChange"
 
 154     delete = XML::Node.new "delete"
 
 156     delete << current_relations(:visible_relation).to_xml_node
 
 157     delete << current_relations(:used_relation).to_xml_node
 
 158     delete << current_ways(:used_way).to_xml_node
 
 159     delete << current_nodes(:node_used_by_relationship).to_xml_node
 
 163     post :upload, :id => 1
 
 164     assert_response :success, 
 
 165       "can't upload a deletion diff to changeset: #{@response.body}"
 
 167     # check that everything was deleted
 
 168     assert_equal false, Node.find(current_nodes(:node_used_by_relationship).id).visible
 
 169     assert_equal false, Way.find(current_ways(:used_way).id).visible
 
 170     assert_equal false, Relation.find(current_relations(:visible_relation).id).visible
 
 171     assert_equal false, Relation.find(current_relations(:used_relation).id).visible
 
 175   # test that deleting stuff in a transaction doesn't bypass the checks
 
 176   # to ensure that used elements are not deleted.
 
 177   def test_upload_delete_invalid
 
 178     basic_authorization "test@openstreetmap.org", "test"
 
 180     diff = XML::Document.new
 
 181     diff.root = XML::Node.new "osmChange"
 
 182     delete = XML::Node.new "delete"
 
 184     delete << current_relations(:visible_relation).to_xml_node
 
 185     delete << current_ways(:used_way).to_xml_node
 
 186     delete << current_nodes(:node_used_by_relationship).to_xml_node
 
 190     post :upload, :id => 1
 
 191     assert_response :precondition_failed, 
 
 192       "shouldn't be able to upload a invalid deletion diff: #{@response.body}"
 
 194     # check that nothing was, in fact, deleted
 
 195     assert_equal true, Node.find(current_nodes(:node_used_by_relationship).id).visible
 
 196     assert_equal true, Way.find(current_ways(:used_way).id).visible
 
 197     assert_equal true, Relation.find(current_relations(:visible_relation).id).visible
 
 201   # upload something which creates new objects and inserts them into
 
 202   # existing containers using placeholders.
 
 203   def test_upload_complex
 
 204     basic_authorization "test@openstreetmap.org", "test"
 
 206     # simple diff to create a node way and relation using placeholders
 
 210   <node id='-1' lon='0' lat='0' changeset='1'>
 
 211    <tag k='foo' v='bar'/>
 
 212    <tag k='baz' v='bat'/>
 
 216   <way id='1' changeset='1' version='1'>
 
 220   <relation id='1' changeset='1' version='1'>
 
 221    <member type='way' role='some' ref='3'/>
 
 222    <member type='node' role='some' ref='-1'/>
 
 223    <member type='relation' role='some' ref='3'/>
 
 231     post :upload, :id => 1
 
 232     assert_response :success, 
 
 233       "can't upload a complex diff to changeset: #{@response.body}"
 
 235     # check the returned payload
 
 236     assert_select "osm[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
 
 237     assert_select "osm>node", 1
 
 238     assert_select "osm>way", 1
 
 239     assert_select "osm>relation", 1
 
 241     # inspect the response to find out what the new element IDs are
 
 242     doc = XML::Parser.string(@response.body).parse
 
 243     new_node_id = doc.find("//osm/node").first["new_id"].to_i
 
 245     # check that the changes made it into the database
 
 246     assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
 
 247     assert_equal [new_node_id, 3], Way.find(1).nds, "way nodes should match"
 
 248     Relation.find(1).members.each do |type,id,role|
 
 250         assert_equal new_node_id, id, "relation should contain new node"
 
 256   # create a diff which references several changesets, which should cause
 
 257   # a rollback and none of the diff gets committed
 
 258   def test_upload_invalid_changesets
 
 259     basic_authorization "test@openstreetmap.org", "test"
 
 261     # simple diff to create a node way and relation using placeholders
 
 265   <node id='1' lon='0' lat='0' changeset='1' version='1'/>
 
 266   <way id='1' changeset='1' version='1'>
 
 271   <relation id='1' changeset='1' version='1'>
 
 272    <member type='way' role='some' ref='3'/>
 
 273    <member type='node' role='some' ref='5'/>
 
 274    <member type='relation' role='some' ref='3'/>
 
 278   <node id='-1' changeset='4'>
 
 279    <tag k='foo' v='bar'/>
 
 280    <tag k='baz' v='bat'/>
 
 285     # cache the objects before uploading them
 
 286     node = current_nodes(:visible_node)
 
 287     way = current_ways(:visible_way)
 
 288     rel = current_relations(:visible_relation)
 
 292     post :upload, :id => 1
 
 293     assert_response :conflict, 
 
 294       "uploading a diff with multiple changsets should have failed"
 
 296     # check that objects are unmodified
 
 297     assert_nodes_are_equal(node, Node.find(1))
 
 298     assert_ways_are_equal(way, Way.find(1))
 
 302   # upload multiple versions of the same element in the same diff.
 
 303   def test_upload_multiple_valid
 
 304     basic_authorization "test@openstreetmap.org", "test"
 
 306     # change the location of a node multiple times, each time referencing
 
 307     # the last version. doesn't this depend on version numbers being
 
 312   <node id='1' lon='0' lat='0' changeset='1' version='1'/>
 
 313   <node id='1' lon='1' lat='0' changeset='1' version='2'/>
 
 314   <node id='1' lon='1' lat='1' changeset='1' version='3'/>
 
 315   <node id='1' lon='1' lat='2' changeset='1' version='4'/>
 
 316   <node id='1' lon='2' lat='2' changeset='1' version='5'/>
 
 317   <node id='1' lon='3' lat='2' changeset='1' version='6'/>
 
 318   <node id='1' lon='3' lat='3' changeset='1' version='7'/>
 
 319   <node id='1' lon='9' lat='9' changeset='1' version='8'/>
 
 326     post :upload, :id => 1
 
 327     assert_response :success, 
 
 328       "can't upload multiple versions of an element in a diff: #{@response.body}"
 
 332   # upload multiple versions of the same element in the same diff, but
 
 333   # keep the version numbers the same.
 
 334   def test_upload_multiple_duplicate
 
 335     basic_authorization "test@openstreetmap.org", "test"
 
 340   <node id='1' lon='0' lat='0' changeset='1' version='1'/>
 
 341   <node id='1' lon='1' lat='1' changeset='1' version='1'/>
 
 348     post :upload, :id => 1
 
 349     assert_response :conflict, 
 
 350       "shouldn't be able to upload the same element twice in a diff: #{@response.body}"
 
 354   # try to upload some elements without specifying the version
 
 355   def test_upload_missing_version
 
 356     basic_authorization "test@openstreetmap.org", "test"
 
 361   <node id='1' lon='1' lat='1' changeset='1'/>
 
 368     post :upload, :id => 1
 
 369     assert_response :bad_request, 
 
 370       "shouldn't be able to upload an element without version: #{@response.body}"
 
 374   # when we make some simple changes we get the same changes back from the 
 
 376   def test_diff_download_simple
 
 377     basic_authorization(users(:normal_user).email, "test")
 
 379     # create a temporary changeset
 
 380     content "<osm><changeset>" +
 
 381       "<tag k='created_by' v='osm test suite checking changesets'/>" + 
 
 384     assert_response :success
 
 385     changeset_id = @response.body.to_i
 
 391   <node id='1' lon='0' lat='0' changeset='#{changeset_id}' version='1'/>
 
 392   <node id='1' lon='1' lat='0' changeset='#{changeset_id}' version='2'/>
 
 393   <node id='1' lon='1' lat='1' changeset='#{changeset_id}' version='3'/>
 
 394   <node id='1' lon='1' lat='2' changeset='#{changeset_id}' version='4'/>
 
 395   <node id='1' lon='2' lat='2' changeset='#{changeset_id}' version='5'/>
 
 396   <node id='1' lon='3' lat='2' changeset='#{changeset_id}' version='6'/>
 
 397   <node id='1' lon='3' lat='3' changeset='#{changeset_id}' version='7'/>
 
 398   <node id='1' lon='9' lat='9' changeset='#{changeset_id}' version='8'/>
 
 405     post :upload, :id => changeset_id
 
 406     assert_response :success, 
 
 407       "can't upload multiple versions of an element in a diff: #{@response.body}"
 
 409     get :download, :id => changeset_id
 
 410     assert_response :success
 
 412     assert_select "osmChange", 1
 
 413     assert_select "osmChange>modify", 8
 
 414     assert_select "osmChange>modify>node", 8
 
 418   # when we make some complex changes we get the same changes back from the 
 
 420   def test_diff_download_complex
 
 421     basic_authorization(users(:normal_user).email, "test")
 
 423     # create a temporary changeset
 
 424     content "<osm><changeset>" +
 
 425       "<tag k='created_by' v='osm test suite checking changesets'/>" + 
 
 428     assert_response :success
 
 429     changeset_id = @response.body.to_i
 
 435   <node id='1' lon='0' lat='0' changeset='#{changeset_id}' version='1'/>
 
 438   <node id='-1' lon='9' lat='9' changeset='#{changeset_id}' version='0'/>
 
 439   <node id='-2' lon='8' lat='9' changeset='#{changeset_id}' version='0'/>
 
 440   <node id='-3' lon='7' lat='9' changeset='#{changeset_id}' version='0'/>
 
 443   <node id='3' lon='20' lat='15' changeset='#{changeset_id}' version='1'/>
 
 444   <way id='1' changeset='#{changeset_id}' version='1'>
 
 456     post :upload, :id => changeset_id
 
 457     assert_response :success, 
 
 458       "can't upload multiple versions of an element in a diff: #{@response.body}"
 
 460     get :download, :id => changeset_id
 
 461     assert_response :success
 
 463     assert_select "osmChange", 1
 
 464     assert_select "osmChange>create", 3
 
 465     assert_select "osmChange>delete", 1
 
 466     assert_select "osmChange>modify", 2
 
 467     assert_select "osmChange>create>node", 3
 
 468     assert_select "osmChange>delete>node", 1 
 
 469     assert_select "osmChange>modify>node", 1
 
 470     assert_select "osmChange>modify>way", 1