amf get*_history tests and related 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   def test_getway_history
191     latest = current_ways(:way_with_versions)
192     amf_content "getway_history", "/1", [latest.id]
193     post :amf_read
194     assert_response :success
195     amf_parse_response
196     history = amf_result("/1")
197
198     # ['way',wayid,history]
199     assert_equal history[0], 'way'
200     assert_equal history[1], latest.id
201     assert_equal history[2].first[0], latest.version
202     assert_equal history[2].last[0], ways(:way_with_versions_v1).version
203   end
204
205   def test_getway_history_nonexistent
206     amf_content "getway_history", "/1", [0]
207     post :amf_read
208     assert_response :success
209     amf_parse_response
210     history = amf_result("/1")
211
212     # ['way',wayid,history]
213     assert_equal history[0], 'way'
214     assert_equal history[1], 0
215     assert history[2].empty?
216   end
217
218   def test_getnode_history
219     latest = current_nodes(:node_with_versions)
220     amf_content "getnode_history", "/1", [latest.id]
221     post :amf_read
222     assert_response :success
223     amf_parse_response
224     history = amf_result("/1")
225
226     # ['node',nodeid,history]
227     assert_equal history[0], 'node'
228     assert_equal history[1], latest.id
229     assert_equal history[2].first[0], latest.timestamp.to_i
230     assert_equal history[2].last[0], nodes(:node_with_versions_v1).timestamp.to_i
231   end
232
233   def test_getnode_history_nonexistent
234     amf_content "getnode_history", "/1", [0]
235     post :amf_read
236     assert_response :success
237     amf_parse_response
238     history = amf_result("/1")
239
240     # ['node',nodeid,history]
241     assert_equal history[0], 'node'
242     assert_equal history[1], 0
243     assert history[2].empty?
244   end
245
246
247   # ************************************************************
248   # AMF Helper functions
249
250   # Get the result record for the specified ID
251   # It's an assertion FAIL if the record does not exist
252   def amf_result ref
253     assert @amf_result.has_key?("#{ref}/onResult")
254     @amf_result["#{ref}/onResult"]
255   end
256
257   # Encode the AMF message to invoke "target" with parameters as
258   # the passed data. The ref is used to retrieve the results.
259   def amf_content(target, ref, data)
260     a,b=1.divmod(256)
261     c = StringIO.new()
262     c.write 0.chr+0.chr   # version 0
263     c.write 0.chr+0.chr   # n headers
264     c.write a.chr+b.chr   # n bodies
265     c.write AMF.encodestring(target)
266     c.write AMF.encodestring(ref)
267     c.write [-1].pack("N")
268     c.write AMF.encodevalue(data)
269
270     @request.env["RAW_POST_DATA"] = c.string
271   end
272
273   # Parses the @response object as an AMF messsage.
274   # The result is a hash of message_ref => data.
275   # The attribute @amf_result is initialised to this hash.
276   def amf_parse_response
277     if @response.body.class.to_s == 'Proc'
278       res = StringIO.new()
279       @response.body.call @response, res
280       req = StringIO.new(res.string)
281     else
282       req = StringIO.new(@response.body)
283     end
284     req.read(2)   # version
285
286     # parse through any headers
287         headers=AMF.getint(req)                                 # Read number of headers
288         headers.times do                                                # Read each header
289           name=AMF.getstring(req)                               #  |
290           req.getc                                                              #  | skip boolean
291           value=AMF.getvalue(req)                               #  |
292         end
293
294     # parse through responses
295     results = {}
296     bodies=AMF.getint(req)                                      # Read number of bodies
297         bodies.times do                                                 # Read each body
298           message=AMF.getstring(req)                    #  | get message name
299           index=AMF.getstring(req)                              #  | get index in response sequence
300           bytes=AMF.getlong(req)                                #  | get total size in bytes
301           args=AMF.getvalue(req)                                #  | get response (probably an array)
302       results[message] = args
303     end
304     @amf_result = results
305     results
306   end
307
308 end