1st amf_controller tests, and some basic sanity check 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   # Get the result record for the specified ID
158   # It's an assertion FAIL if the record does not exist
159   def amf_result ref
160     assert @amf_result.has_key?("#{ref}/onResult")
161     @amf_result["#{ref}/onResult"]
162   end
163
164   # Encode the AMF message to invoke "target" with parameters as
165   # the passed data. The ref is used to retrieve the results.
166   def amf_content(target, ref, data)
167     a,b=1.divmod(256)
168     c = StringIO.new()
169     c.write 0.chr+0.chr   # version 0
170     c.write 0.chr+0.chr   # n headers
171     c.write a.chr+b.chr   # n bodies
172     c.write AMF.encodestring(target)
173     c.write AMF.encodestring(ref)
174     c.write [-1].pack("N")
175     c.write AMF.encodevalue(data)
176
177     @request.env["RAW_POST_DATA"] = c.string
178   end
179
180   # Parses the @response object as an AMF messsage.
181   # The result is a hash of message_ref => data.
182   # The attribute @amf_result is initialised to this hash.
183   def amf_parse_response
184     if @response.body.class.to_s == 'Proc'
185       res = StringIO.new()
186       @response.body.call @response, res
187       req = StringIO.new(res.string)
188     else
189       req = StringIO.new(@response.body)
190     end
191     req.read(2)   # version
192
193     # parse through any headers
194         headers=AMF.getint(req)                                 # Read number of headers
195         headers.times do                                                # Read each header
196           name=AMF.getstring(req)                               #  |
197           req.getc                                                              #  | skip boolean
198           value=AMF.getvalue(req)                               #  |
199         end
200
201     # parse through responses
202     results = {}
203     bodies=AMF.getint(req)                                      # Read number of bodies
204         bodies.times do                                                 # Read each body
205           message=AMF.getstring(req)                    #  | get message name
206           index=AMF.getstring(req)                              #  | get index in response sequence
207           bytes=AMF.getlong(req)                                #  | get total size in bytes
208           args=AMF.getvalue(req)                                #  | get response (probably an array)
209       results[message] = args
210     end
211     @amf_result = results
212     results
213   end
214
215 end