(module protocol-test mzscheme
(require (planet "test.ss" ("schematics" "schemeunit.plt" 1 1)))
(require (lib "url.ss" "net")
"protocol.ss"
"base.ss"
"util.ss")
(provide protocol-tests)
(define body-string
"<?xml version=\"1.0\"?>
<methodCall>
<methodName>fooBar</methodName>
<params>
<param>
<value>
<int>1</int>
</value>
</param>
<param>
<value>
<double>2.0</double>
</value>
</param>
<param>
<value>
<string>3</string>
</value>
</param>
</params>
</methodCall>")
(define generic-headers
"HTTP/1.1 200 OK\r\nContent-Type:text/xml\r\n\r\n")
(define fault-response-string
"<?xml version=\"1.0\"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value><int>4</int></value>
</member>
<member>
<name>faultString</name>
<value><string>Too many parameters.</string></value>
</member>
</struct>
</value>
</fault>
</methodResponse>")
(define successful-response-string
"<?xml version=\"1.0\"?>
<methodResponse>
<params>
<param>
<value><string>Hello!</string></value>
</param>
</params>
</methodResponse>")
(define protocol-tests
(make-test-suite
"All tests for protocol"
(make-test-case
"Method call encoded correctly"
(assert-equal? (encode-xmlrpc-call "fooBar" 1 2.0 "3")
'(methodCall
(methodName "fooBar")
(params
(param (value (int "1")))
(param (value (double "2.0")))
(param (value (string "3")))))))
(make-test-case
"Method call written correctly"
(let ((op (open-output-string)))
(write-xmlrpc-call
(encode-xmlrpc-call "fooBar" 1 2.0 "3") op)
(assert-equal?
(get-output-string op)
body-string)))
(make-test-case
"Response with bad HTTP code raises exn"
(assert-exn
exn:xmlrpc?
(lambda ()
(read-xmlrpc-response
(open-input-string "HTTP/1.0 500 Dead\r\n")))))
(make-test-case
"Empty response raises exn"
(assert-exn
exn:xmlrpc?
(lambda ()
(read-xmlrpc-response
(open-input-string "")))))
(make-test-case
"Fault response is parsed correctly and raises exn"
(let ((resp
(read-xmlrpc-response
(open-input-string
(string-append generic-headers
fault-response-string)))))
(assert-equal?
'(*TOP*
(*PI* xml "version=\"1.0\"")
(methodResponse
(fault
(value
(struct
(member (name "faultCode")
(value (int "4")))
(member (name "faultString")
(value (string "Too many parameters."))))))))
resp)))
(make-test-case
"Successful response is parsed correctly"
(let ((resp
(read-xmlrpc-response
(open-input-string
(string-append generic-headers
successful-response-string)))))
(assert-equal?
'(*TOP*
(*PI* xml "version=\"1.0\"")
(methodResponse
(params
(param
(value (string "Hello!"))))))
resp)))
(make-test-case
"Successful response decoded correctly"
(assert-equal?
(decode-xmlrpc-response
(open-input-string
(string-append generic-headers
successful-response-string)))
"Hello!"))
(make-test-case
"Fault response decoded correctly"
(assert-exn
(lambda (exn)
(and (exn:xmlrpc:fault? exn)
(assert = (exn:xmlrpc:fault-code exn) 4)
(assert string=?
(exn-message exn)
"Too many parameters.")))
(lambda ()
(decode-xmlrpc-response
(open-input-string
(string-append generic-headers
fault-response-string))))))
(make-test-case
"Round-trip XML-RPC call is successful"
(assert
string=?
(decode-xmlrpc-response
(make-xmlrpc-call
(string->url "http://betty.userland.com/RPC2")
(encode-xmlrpc-call "examples.getStateName" 40)))
"South Carolina"))
(make-test-case
"Round-trip XML-RPC with invalid response handled ok"
(assert
string=?
(decode-xmlrpc-response
(make-xmlrpc-call
(string->url "http://betty.userland.com/RPC2")
(encode-xmlrpc-call "examples.getStateName" 60)))
""))
))
)