a few more amf tests and associated bug fixes
[rails.git] / test / functional / amf_controller_test.rb
1 require File.dirname(__FILE__) + '/../test_helper'
2 require 'stringio'
3 include Potlatch
4
5 class AmfControllerTest < ActionController::TestCase
6   api_fixtures
7
8   def test_getway
9     # check a visible way
10     id = current_ways(:visible_way).id
11     amf_content "getway", "/1", [id]
12     post :amf_read
13     assert_response :success
14     amf_parse_response
15     assert_equal amf_result("/1")[0], id
16   end
17
18   def test_getway_invisible
19     # check an invisible way
20     id = current_ways(:invisible_way).id
21     amf_content "getway", "/1", [id]
22     post :amf_read
23     assert_response :success
24     amf_parse_response
25     way = amf_result("/1")
26     assert_equal way[0], id
27     assert way[1].empty? and way[2].empty?
28   end
29
30   def test_getway_nonexistent
31     # check chat a non-existent way is not returned
32     amf_content "getway", "/1", [0]
33     post :amf_read
34     assert_response :success
35     amf_parse_response
36     way = amf_result("/1")
37     assert_equal way[0], 0
38     assert way[1].empty? and way[2].empty?
39   end
40
41   def test_whichways
42     node = current_nodes(:used_node_1)
43     minlon = node.lon-0.1
44     minlat = node.lat-0.1
45     maxlon = node.lon+0.1
46     maxlat = node.lat+0.1
47     amf_content "whichways", "/1", [minlon, minlat, maxlon, maxlat]
48     post :amf_read
49     assert_response :success
50     amf_parse_response 
51
52     # check contents of message
53     map = amf_result "/1"
54     assert map[0].include?(current_ways(:used_way).id)
55     assert !map[0].include?(current_ways(:invisible_way).id)
56   end
57
58   def test_whichways_toobig
59     bbox = [-0.1,-0.1,1.1,1.1]
60     amf_content "whichways", "/1", bbox
61     post :amf_read
62     assert_response :success
63     amf_parse_response 
64
65     # FIXME: whichways needs to reject large bboxes and the test needs to check for this
66     map = amf_result "/1"
67     assert map[0].empty? and map[1].empty? and map[2].empty?
68   end
69
70   def test_whichways_badlat
71     bboxes = [[0,0.1,0.1,0], [-0.1,80,0.1,70], [0.24,54.34,0.25,54.33]]
72     bboxes.each do |bbox|
73       amf_content "whichways", "/1", bbox
74       post :amf_read
75       assert_response :success
76       amf_parse_response 
77
78       # FIXME: whichways needs to reject bboxes with illegal lats and the test needs to check for this
79       map = amf_result "/1"
80       assert map[0].empty? and map[1].empty? and map[2].empty?
81     end
82   end
83
84   def test_whichways_badlon
85     bboxes = [[80,-0.1,70,0.1], [54.34,0.24,54.33,0.25]]
86     bboxes.each do |bbox|
87       amf_content "whichways", "/1", bbox
88       post :amf_read
89       assert_response :success
90       amf_parse_response
91
92       # FIXME: whichways needs to reject bboxes with illegal lons and the test needs to check for this
93       map = amf_result "/1"
94       assert map[0].empty? and map[1].empty? and map[2].empty?
95     end
96   end
97
98   def test_whichways_deleted
99     node = current_nodes(:used_node_1)
100     minlon = node.lon-0.1
101     minlat = node.lat-0.1
102     maxlon = node.lon+0.1
103     maxlat = node.lat+0.1
104     amf_content "whichways_deleted", "/1", [minlon, minlat, maxlon, maxlat]
105     post :amf_read
106     assert_response :success
107     amf_parse_response
108
109     # check contents of message
110     ways = amf_result "/1"
111     assert ways[0].include?(current_ways(:invisible_way).id)
112     assert !ways[0].include?(current_ways(:used_way).id)
113   end
114
115   def test_whichways_deleted_toobig
116     bbox = [-0.1,-0.1,1.1,1.1]
117     amf_content "whichways_deleted", "/1", bbox
118     post :amf_read
119     assert_response :success
120     amf_parse_response 
121
122     ways = amf_result "/1"
123     assert ways[0].empty?
124   end
125
126   def test_getrelation
127     id = current_relations(:visible_relation).id
128     amf_content "getrelation", "/1", [id]
129     post :amf_read
130     assert_response :success
131     amf_parse_response
132     assert_equal amf_result("/1")[0], id
133   end
134
135   def test_getrelation_invisible
136     id = current_relations(:invisible_relation).id
137     amf_content "getrelation", "/1", [id]
138     post :amf_read
139     assert_response :success
140     amf_parse_response
141     rel = amf_result("/1")
142     assert_equal rel[0], id
143     assert rel[1].empty? and rel[2].empty?
144   end
145
146   def test_getrelation_nonexistent
147     id = 0
148     amf_content "getrelation", "/1", [id]
149     post :amf_read
150     assert_response :success
151     amf_parse_response
152     rel = amf_result("/1")
153     assert_equal rel[0], id
154     assert rel[1].empty? and rel[2].empty?
155   end
156
157   def test_getway_old
158     # try to get the last visible version (specified by <0) (should be current version)
159     latest = current_ways(:way_with_versions)
160     # try to get version 1
161     v1 = ways(:way_with_versions_v1)
162     {latest => -1, v1 => v1.version}.each do |way, v|
163       amf_content "getway_old", "/1", [way.id, v]
164       post :amf_read
165       assert_response :success
166       amf_parse_response
167       returned_way = amf_result("/1")
168       assert_equal returned_way[1], way.id
169       assert_equal returned_way[4], way.version
170     end
171   end
172
173   def test_getway_old_nonexistent
174     # try to get the last version+10 (shoudn't exist)
175     latest = current_ways(:way_with_versions)
176     # try to get last visible version of non-existent way
177     # try to get specific version of non-existent way
178     {nil => -1, nil => 1, latest => latest.version + 10}.each do |way, v|
179       amf_content "getway_old", "/1", [way.nil? ? 0 : way.id, v]
180       post :amf_read
181       assert_response :success
182       amf_parse_response
183       returned_way = amf_result("/1")
184       assert returned_way[2].empty?
185       assert returned_way[3].empty?
186       assert returned_way[4] < 0
187     end
188   end
189
190
191   # ************************************************************
192   # AMF Helper functions
193
194   # Get the result record for the specified ID
195   # It's an assertion FAIL if the record does not exist
196   def amf_result ref
197     assert @amf_result.has_key?("#{ref}/onResult")
198     @amf_result["#{ref}/onResult"]
199   end
200
201   # Encode the AMF message to invoke "target" with parameters as
202   # the passed data. The ref is used to retrieve the results.
203   def amf_content(target, ref, data)
204     a,b=1.divmod(256)
205     c = StringIO.new()
206     c.write 0.chr+0.chr   # version 0
207     c.write 0.chr+0.chr   # n headers
208     c.write a.chr+b.chr   # n bodies
209     c.write AMF.encodestring(target)
210     c.write AMF.encodestring(ref)
211     c.write [-1].pack("N")
212     c.write AMF.encodevalue(data)
213
214     @request.env["RAW_POST_DATA"] = c.string
215   end
216
217   # Parses the @response object as an AMF messsage.
218   # The result is a hash of message_ref => data.
219   # The attribute @amf_result is initialised to this hash.
220   def amf_parse_response
221     if @response.body.class.to_s == 'Proc'
222       res = StringIO.new()
223       @response.body.call @response, res
224       req = StringIO.new(res.string)
225     else
226       req = StringIO.new(@response.body)
227     end
228     req.read(2)   # version
229
230     # parse through any headers
231         headers=AMF.getint(req)                                 # Read number of headers
232         headers.times do                                                # Read each header
233           name=AMF.getstring(req)                               #  |
234           req.getc                                                              #  | skip boolean
235           value=AMF.getvalue(req)                               #  |
236         end
237
238     # parse through responses
239     results = {}
240     bodies=AMF.getint(req)                                      # Read number of bodies
241         bodies.times do                                                 # Read each body
242           message=AMF.getstring(req)                    #  | get message name
243           index=AMF.getstring(req)                              #  | get index in response sequence
244           bytes=AMF.getlong(req)                                #  | get total size in bytes
245           args=AMF.getvalue(req)                                #  | get response (probably an array)
246       results[message] = args
247     end
248     @amf_result = results
249     results
250   end
251
252 end