Support for Status.net API with OAuth.
[twitter-api-test-suite:twitter-api-test-suite.git] / includes / abstract.RestTest.php
1 <?php
2
3 require_once(dirname(__FILE__) . '/OAuth.php');
4 require_once('PHPUnit/Framework.php');
5
6 abstract class RestTest extends PHPUnit_Framework_TestCase
7 {
8
9     /**
10     * @var object cURL handle
11     */
12     public $curl;
13
14     /**
15     * @var string Placeholder for 'GET', 'POST', 'PUT', 'DELETE'
16     */
17     public $method;
18
19     /**
20     * @var string Returned headers
21     */
22     public $headers;
23
24     /**
25     * @var string Returned body
26     */
27     public $body;
28
29     /**
30     * @var object Simple XML, generated by validateBodyIsXML()
31     */
32     public $xml;
33
34     /**
35     * @var object Json, generated by validateBodyIsJson()
36     */
37     public $json;
38
39     /**
40     * @var bool
41     */
42     public $debug = false;
43
44
45     /**
46     * PHPUnit setup
47     */
48     function setUp()
49     {
50         if(!function_exists('curl_init')) {
51             die('The function "curl_init" not found, aborting!');
52         }
53         parent::setUp();
54
55     }
56
57
58     /**
59     * Initialize. This method must be called before all others
60     *
61     * @param string $url
62     * @param string $method 'GET', 'PUT', 'POST', or 'DELETE'
63     * @param string|array $data
64     */
65     protected function init($url, $method, $data = null)
66     {
67         if (isset($this->curl)) {
68             curl_close($this->curl);
69             unset($this->curl);
70         }
71         unset($this->method, $this->headers, $this->body, $this->xml, $this->json);
72
73         $this->curl = curl_init();
74         curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
75         curl_setopt($this->curl, CURLOPT_HEADER, true);
76         curl_setopt($this->curl, CURLOPT_URL, $url);
77         curl_setopt($this->curl, CURLOPT_PORT, $GLOBALS['CONFIG']['PORT']);
78
79         // Debug
80         if ($GLOBALS['CONFIG']['DEBUG']) {
81             curl_setopt($this->curl, CURLOPT_VERBOSE, 1);
82             $this->debug = true;
83         }
84
85         // Method
86         if ('GET' == strtoupper($method)) {
87             $this->initGET();
88         }
89         elseif ('PUT' == strtoupper($method)) {
90             $this->initPUT($data);
91         }
92         elseif ('POST' == strtoupper($method)) {
93             $this->initPOST($data);
94         }
95         elseif ('DELETE' == strtoupper($method)) {
96             $this->initDELETE();
97         }
98         else {
99             die('Unsuported method. Use GET, PUT, POST, or DELETE.');
100         }
101
102     }
103
104
105     /**
106     * Initalize GET
107     */
108     private function initGET()
109     {
110         $this->method = 'GET';
111         curl_setopt($this->curl, CURLOPT_HTTPGET, true);
112
113     }
114
115
116     /**
117     * Initalize PUT
118     *
119     * @param string $data
120     */
121     private function initPUT($data = null)
122     {
123         $this->method = 'PUT';
124         curl_setopt($this->curl, CURLOPT_PUT, true);
125
126         if ($data != null)
127         {
128             $tmp = tmpfile();
129             fwrite($tmp, $data);
130             fseek($tmp, 0);
131             curl_setopt($this->curl, CURLOPT_INFILE, $tmp);
132             curl_setopt($this->curl, CURLOPT_INFILESIZE, strlen($data));
133             // TODO: Check, is this always XML?
134             // curl_setopt($this->curl, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
135         }
136
137
138     }
139
140
141     /**
142     * Initalize POST
143     *
144     * @param string|array $data
145     */
146     private function initPOST($data = null)
147     {
148         $this->method = 'POST';
149         curl_setopt($this->curl, CURLOPT_POST, true);
150         if ($data != null) {
151             curl_setopt($this->curl, CURLOPT_POSTFIELDS, $data);
152         }
153
154     }
155
156
157     /**
158     * Initalize DELETE
159     */
160     private function initDELETE()
161     {
162         $this->method = 'DELETE';
163         curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
164         // TODO: Not sure about this one... Does it take data, or what?
165
166     }
167
168
169     /**
170     * Set CURLOPT_HTTPHEADER
171     *
172     * @param string $headers
173     */
174     protected function setHeaders($headers)
175     {
176         curl_setopt($this->curl, CURLOPT_HTTPHEADER, $headers);
177     }
178
179
180     /**
181     * Set Curl SSH hacks
182     *
183     */
184     protected function setSSH()
185     {
186
187         curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false);
188         curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, 0);
189     }
190
191
192     /**
193     * Set CURLOPT_PORT
194     *
195     */
196     protected function setPort($port)
197     {
198         curl_setopt($this->curl, CURLOPT_PORT, $port);
199     }
200
201     /**
202     * Perform a cURL session, store returned headers and body, optionaly
203     * validate and store a SimpleXML or Json representation of the body
204     *
205     * @param string $format 'XML', or 'JSON'
206     */
207     protected function exec($format = null)
208     {
209         $response = curl_exec($this->curl);
210
211         $error = curl_error($this->curl);
212         $this->assertTrue((bool)empty($error), 'Curl error: ' . $error);
213
214         // Extract the headers and body
215         $header_size = curl_getinfo($this->curl, CURLINFO_HEADER_SIZE);
216         $this->headers = substr($response, 0, $header_size);
217         $this->body = substr($response, $header_size);
218
219         // Auto validate and convert?
220         if ('XML' == strtoupper($format)) {
221             $this->validateBodyIsXML();
222         }
223         elseif ('JSON' == strtoupper($format)) {
224             $this->validateBodyIsJson();
225         }
226
227     }
228
229
230     /**
231     * Validate CURLINFO_HTTP_CODE
232     *
233     * @param int $status_code
234     */
235     protected function validateReturnStatus($status_code)
236     {
237         $ret_status_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE);
238         $err = "Status codes do not match. We want: $status_code, we got: $ret_status_code";
239         if ($this->debug) $err .= "\n" . $this->headers . "\n" . $this->body;
240         $this->assertTrue($ret_status_code == $status_code, $err);
241
242     }
243
244
245     /**
246     * Validate and store a SimpleXML representation of the body
247     */
248     protected function validateBodyIsXML()
249     {
250         // Validate and create a Simple XML object we can test against
251         $xml = @simplexml_load_string($this->body);
252         if($xml === false) {
253             $err = "Body is not valid XML";
254             if ($this->debug) $err .= "\n" . $this->body;
255             $this->assertTrue(false, $err);
256
257         }
258         $namespaces = $xml->getNamespaces(true);
259         foreach ($namespaces as $prefix => $ns) {
260             $xml->registerXPathNamespace($prefix, $ns);
261         }
262
263         $this->xml = $xml;
264
265     }
266
267     /**
268     * Validate and store a Json representation of the body
269     */
270     protected function validateBodyIsJson()
271     {
272         // Validare and create a json object we can test against
273         $json = json_decode($this->body);
274         if ($json == null) {
275             $err = "Body is not valid JSON";
276             if ($this->debug) $err .= "\n" . $this->body;
277             $this->assertTrue(false, $err);
278         }
279
280         $this->json = $json;
281
282     }
283
284
285     /**
286     * Helper method, random MD5
287     */
288     public function rmd5() {
289         return md5(uniqid(mt_rand(), true));
290
291     }
292
293 }