assert_select "osm>changeset[id=#{changeset_id}]", 1
end
+ ##
+ # test that the user who opened a change can close it
def test_close
- # FIXME FIXME FIXME!
+ basic_authorization "test@openstreetmap.org", "test"
+
+ put :close, :id => changesets(:normal_user_first_change).id
+ assert_response :success
+ end
+
+ ##
+ # test that a different user can't close another user's changeset
+ def test_close_invalid
+ basic_authorization "test@example.com", "test"
+
+ put :close, :id => changesets(:normal_user_first_change).id
+ assert_response :conflict
+ assert_equal "The user doesn't own that changeset", @response.body
end
##
"can't upload a simple valid creation to changeset: #{@response.body}"
# check the returned payload
- assert_select "osm[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
- assert_select "osm>node", 1
- assert_select "osm>way", 1
- assert_select "osm>relation", 1
+ assert_select "diffResult[version=#{API_VERSION}][generator=\"OpenStreetMap server\"]", 1
+ assert_select "diffResult>node", 1
+ assert_select "diffresult>way", 1
+ assert_select "diffResult>relation", 1
# inspect the response to find out what the new element IDs are
doc = XML::Parser.string(@response.body).parse
- new_node_id = doc.find("//osm/node").first["new_id"].to_i
- new_way_id = doc.find("//osm/way").first["new_id"].to_i
- new_rel_id = doc.find("//osm/relation").first["new_id"].to_i
+ new_node_id = doc.find("//diffResult/node").first["new_id"].to_i
+ new_way_id = doc.find("//diffResult/way").first["new_id"].to_i
+ new_rel_id = doc.find("//diffResult/relation").first["new_id"].to_i
# check the old IDs are all present and negative one
- assert_equal -1, doc.find("//osm/node").first["old_id"].to_i
- assert_equal -1, doc.find("//osm/way").first["old_id"].to_i
- assert_equal -1, doc.find("//osm/relation").first["old_id"].to_i
+ assert_equal -1, doc.find("//diffResult/node").first["old_id"].to_i
+ assert_equal -1, doc.find("//diffResult/way").first["old_id"].to_i
+ assert_equal -1, doc.find("//diffResult/relation").first["old_id"].to_i
# check the versions are present and equal one
- assert_equal 1, doc.find("//osm/node").first["new_version"].to_i
- assert_equal 1, doc.find("//osm/way").first["new_version"].to_i
- assert_equal 1, doc.find("//osm/relation").first["new_version"].to_i
+ assert_equal 1, doc.find("//diffResult/node").first["new_version"].to_i
+ assert_equal 1, doc.find("//diffResult/way").first["new_version"].to_i
+ assert_equal 1, doc.find("//diffResult/relation").first["new_version"].to_i
# check that the changes made it into the database
assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
"can't upload a complex diff to changeset: #{@response.body}"
# check the returned payload
- assert_select "osm[version=#{API_VERSION}][generator=\"#{GENERATOR}\"]", 1
- assert_select "osm>node", 1
- assert_select "osm>way", 1
- assert_select "osm>relation", 1
+ assert_select "diffResult[version=#{API_VERSION}][generator=\"#{GENERATOR}\"]", 1
+ assert_select "diffResult>node", 1
+ assert_select "diffResult>way", 1
+ assert_select "diffResult>relation", 1
# inspect the response to find out what the new element IDs are
doc = XML::Parser.string(@response.body).parse
- new_node_id = doc.find("//osm/node").first["new_id"].to_i
+ new_node_id = doc.find("//diffResult/node").first["new_id"].to_i
# check that the changes made it into the database
assert_equal 2, Node.find(new_node_id).tags.size, "new node should have two tags"
# get the bounding box back from the changeset
get :read, :id => changeset_id
assert_response :success, "Couldn't read back changeset."
- assert_select "osm>changeset[min_lon=1]", 1
- assert_select "osm>changeset[max_lon=1]", 1
- assert_select "osm>changeset[min_lat=2]", 1
- assert_select "osm>changeset[max_lat=2]", 1
+ assert_select "osm>changeset[min_lon=1.0]", 1
+ assert_select "osm>changeset[max_lon=1.0]", 1
+ assert_select "osm>changeset[min_lat=2.0]", 1
+ assert_select "osm>changeset[max_lat=2.0]", 1
# add another node to it
with_controller(NodeController.new) do
# get the bounding box back from the changeset
get :read, :id => changeset_id
assert_response :success, "Couldn't read back changeset for the second time."
- assert_select "osm>changeset[min_lon=1]", 1
- assert_select "osm>changeset[max_lon=2]", 1
- assert_select "osm>changeset[min_lat=1]", 1
- assert_select "osm>changeset[max_lat=2]", 1
+ assert_select "osm>changeset[min_lon=1.0]", 1
+ assert_select "osm>changeset[max_lon=2.0]", 1
+ assert_select "osm>changeset[min_lat=1.0]", 1
+ assert_select "osm>changeset[max_lat=2.0]", 1
# add (delete) a way to it
with_controller(WayController.new) do
# get the bounding box back from the changeset
get :read, :id => changeset_id
assert_response :success, "Couldn't read back changeset for the third time."
- assert_select "osm>changeset[min_lon=1]", 1
- assert_select "osm>changeset[max_lon=3]", 1
- assert_select "osm>changeset[min_lat=1]", 1
- assert_select "osm>changeset[max_lat=3]", 1
+ assert_select "osm>changeset[min_lon=1.0]", 1
+ assert_select "osm>changeset[max_lon=3.1]", 1
+ assert_select "osm>changeset[min_lat=1.0]", 1
+ assert_select "osm>changeset[max_lat=3.1]", 1
end
##
check_after_include(changeset_id, -2, 5, [-2, -1, 4, 5])
end
+ ##
+ # test the query functionality of changesets
+ def test_query
+ get :query, :bbox => "-10,-10, 10, 10"
+ assert_response :success, "can't get changesets in bbox"
+ assert_changesets [1,4]
+
+ get :query, :bbox => "4.5,4.5,4.6,4.6"
+ assert_response :success, "can't get changesets in bbox"
+ assert_changesets [1]
+
+ # can't get changesets of user 1 without authenticating
+ get :query, :user => users(:normal_user).id
+ assert_response :not_found, "shouldn't be able to get changesets by non-public user"
+
+ # but this should work
+ basic_authorization "test@openstreetmap.org", "test"
+ get :query, :user => users(:normal_user).id
+ assert_response :success, "can't get changesets by user"
+ assert_changesets [1,3,4]
+
+ get :query, :user => users(:normal_user).id, :open => true
+ assert_response :success, "can't get changesets by user and open"
+ assert_changesets [1,4]
+
+ get :query, :time => '2007-12-31'
+ assert_response :success, "can't get changesets by time-since"
+ assert_changesets [1,2,4,5]
+
+ get :query, :time => '2008-01-01T12:34Z'
+ assert_response :success, "can't get changesets by time-since with hour"
+ assert_changesets [1,2,4,5]
+
+ get :query, :time => '2007-12-31T23:59Z,2008-01-01T00:01Z'
+ assert_response :success, "can't get changesets by time-range"
+ assert_changesets [1,4,5]
+
+ get :query, :open => 'true'
+ assert_response :success, "can't get changesets by open-ness"
+ assert_changesets [1,2,4]
+ end
+
+ ##
+ # check that errors are returned if garbage is inserted
+ # into query strings
+ def test_query_invalid
+ [ "abracadabra!",
+ "1,2,3,F",
+ ";drop table users;"
+ ].each do |bbox|
+ get :query, :bbox => bbox
+ assert_response :bad_request, "'#{bbox}' isn't a bbox"
+ end
+
+ [ "now()",
+ "00-00-00",
+ ";drop table users;",
+ ",",
+ "-,-"
+ ].each do |time|
+ get :query, :time => time
+ assert_response :bad_request, "'#{time}' isn't a valid time range"
+ end
+
+ [ "me",
+ "foobar",
+ "-1",
+ "0"
+ ].each do |uid|
+ get :query, :user => uid
+ assert_response :bad_request, "'#{uid}' isn't a valid user ID"
+ end
+ end
+
+ ##
+ # check updating tags on a changeset
+ def test_changeset_update
+ basic_authorization "test@openstreetmap.org", "test"
+
+ changeset = changesets(:normal_user_first_change)
+ new_changeset = changeset.to_xml
+ new_tag = XML::Node.new "tag"
+ new_tag['k'] = "tagtesting"
+ new_tag['v'] = "valuetesting"
+ new_changeset.find("//osm/changeset").first << new_tag
+
+ content new_changeset
+ put :update, :id => changeset.id
+ assert_response :success
+
+ assert_select "osm>changeset[id=#{changeset.id}]", 1
+ assert_select "osm>changeset>tag", 2
+ assert_select "osm>changeset>tag[k=tagtesting][v=valuetesting]", 1
+ end
+
+ ##
+ # check that a user different from the one who opened the changeset
+ # can't modify it.
+ def test_changeset_update_invalid
+ basic_authorization "test@example.com", "test"
+
+ changeset = changesets(:normal_user_first_change)
+ new_changeset = changeset.to_xml
+ new_tag = XML::Node.new "tag"
+ new_tag['k'] = "testing"
+ new_tag['v'] = "testing"
+ new_changeset.find("//osm/changeset").first << new_tag
+
+ content new_changeset
+ put :update, :id => changeset.id
+ assert_response :conflict
+ end
+
+ ##
+ # check that a changeset can contain a certain max number of changes.
+ def test_changeset_limits
+ basic_authorization "test@openstreetmap.org", "test"
+
+ # open a new changeset
+ content "<osm><changeset/></osm>"
+ put :create
+ assert_response :success, "can't create a new changeset"
+ cs_id = @response.body.to_i
+
+ # start the counter just short of where the changeset should finish.
+ offset = 10
+ # alter the database to set the counter on the changeset directly,
+ # otherwise it takes about 6 minutes to fill all of them.
+ changeset = Changeset.find(cs_id)
+ changeset.num_changes = Changeset::MAX_ELEMENTS - offset
+ changeset.save!
+
+ with_controller(NodeController.new) do
+ # create a new node
+ content "<osm><node changeset='#{cs_id}' lat='0.0' lon='0.0'/></osm>"
+ put :create
+ assert_response :success, "can't create a new node"
+ node_id = @response.body.to_i
+
+ get :read, :id => node_id
+ assert_response :success, "can't read back new node"
+ node_doc = XML::Parser.string(@response.body).parse
+ node_xml = node_doc.find("//osm/node").first
+
+ # loop until we fill the changeset with nodes
+ offset.times do |i|
+ node_xml['lat'] = rand.to_s
+ node_xml['lon'] = rand.to_s
+ node_xml['version'] = (i+1).to_s
+
+ content node_doc
+ put :update, :id => node_id
+ assert_response :success, "attempt #{i} should have succeeded"
+ end
+
+ # trying again should fail
+ node_xml['lat'] = rand.to_s
+ node_xml['lon'] = rand.to_s
+ node_xml['version'] = offset.to_s
+
+ content node_doc
+ put :update, :id => node_id
+ assert_response :conflict, "final attempt should have failed"
+ end
+
+ changeset = Changeset.find(cs_id)
+ assert_equal Changeset::MAX_ELEMENTS + 1, changeset.num_changes
+ end
+
#------------------------------------------------------------
# utility functions
#------------------------------------------------------------
+ ##
+ # boilerplate for checking that certain changesets exist in the
+ # output.
+ def assert_changesets(ids)
+ assert_select "osm>changeset", ids.size
+ ids.each do |id|
+ assert_select "osm>changeset[id=#{id}]", 1
+ end
+ end
+
##
# call the include method and assert properties of the bbox
def check_after_include(changeset_id, lon, lat, bbox)