#!/bin/sh
#
# Test the XOAUTH2 support in send
#

if test -z "${MH_OBJ_DIR}"; then
    srcdir=`dirname "$0"`/../..
    MH_OBJ_DIR=`cd "${srcdir}" && pwd`; export MH_OBJ_DIR
fi

. "${srcdir}/test/oauth/common.sh"

check_exit '-eq 1' send -

test_send_only_fakehttp() {
    start_fakehttp
    test_send_no_servers "$@"
    check_http_req
}

#
# success cases
#

export XOAUTH
XOAUTH='dXNlcj1ub2JvZHlAZXhhbXBsZS5jb20BYXV0aD1CZWFyZXIgdGVzdC1hY2Nlc3MBAQ=='

# TEST
start_test 'access token ready, smtp server accepts message'

setup_draft

fake_creds <<EOF
access-nobody@example.com: test-access
refresh-nobody@example.com: test-refresh
expire-nobody@example.com: 2000000000
EOF

start_fakesmtp
run_test "send -draft -server 127.0.0.1 -port ${smtp_port} -sasl -saslmech xoauth2 -authservice test -user nobody@example.com"

# TEST
start_test 'expired access token, refresh works, smtp server accepts message'

setup_draft

fake_creds <<EOF
access-nobody@example.com: old-access
refresh-nobody@example.com: test-refresh
expire-nobody@example.com: 1414303986
EOF

expect_http_post_refresh

fake_json_response <<EOF
{
  "access_token": "test-access",
  "token_type": "Bearer",
  "expires_in": 3600
}
EOF

expect_creds <<EOF
access-nobody@example.com: test-access
refresh-nobody@example.com: test-refresh
expire-nobody@example.com:
EOF

test_send

check_creds_private
check_creds

# TEST
start_test 'expired access token, refresh works and gets updated, smtp server accepts message'

setup_draft

fake_creds <<EOF
access-nobody@example.com: old-access
refresh-nobody@example.com: old-refresh
expire-nobody@example.com: 1414303986
EOF

expect_http_post_old_refresh

fake_json_response <<EOF
{
  "access_token": "test-access",
  "refresh_token": "test-refresh",
  "token_type": "Bearer"
}
EOF

expect_creds <<EOF
access-nobody@example.com: test-access
refresh-nobody@example.com: test-refresh
EOF

test_send

check_creds

# TEST
start_test 'access token has no expiration, refresh works, smtp server accepts message'

setup_draft

fake_creds <<EOF
access-nobody@example.com: old-access
refresh-nobody@example.com: test-refresh
EOF

expect_http_post_refresh

fake_json_response <<EOF
{
  "access_token": "test-access",
  "token_type": "Bearer"
}
EOF

expect_creds <<EOF
access-nobody@example.com: test-access
refresh-nobody@example.com: test-refresh
EOF

test_send

check_creds

# TEST
start_test 'no access token, refresh works, smtp server accepts message'

setup_draft

fake_creds <<EOF
refresh-nobody@example.com: test-refresh
EOF

expect_http_post_refresh

fake_json_response <<EOF
{
  "access_token": "test-access",
  "token_type": "Bearer"
}
EOF

expect_creds <<EOF
access-nobody@example.com: test-access
refresh-nobody@example.com: test-refresh
EOF

test_send

check_creds

#
# fail cases
#

setup_draft

# TEST
start_test 'no service definition'

run_test "send -draft -server 127.0.0.1 -port ${smtp_port} -sasl -saslmech xoauth2 -authservice bogus -user nobody@example.com" 'send: Unable to retrieve oauth profile entries: scope is missing'

# TEST
start_test 'no creds file -- should tell user to mhlogin'

rm -f "${MHTMPDIR}/oauth-test"

test_send_only_fakesmtp 'post: no credentials -- run mhlogin -saslmech xoauth2 -authservice test
send: message not delivered to anyone'

# TEST
start_test 'empty creds file -- should tell user to mhlogin'

fake_creds < /dev/null

test_send_only_fakesmtp 'post: user not found in cred file: nobody@example.com
send: message not delivered to anyone'

# TEST
start_test 'garbage creds file'

echo bork | fake_creds

test_send_only_fakesmtp 'post: eof encountered in field "bork"
post: error loading cred file
send: message not delivered to anyone'

# TEST
start_test 'unexpected field in creds file'

fake_creds <<EOF
bork: bork
access-nobody@example.com: test-access
EOF

test_send_only_fakesmtp 'post: error loading cred file: unexpected field
send: message not delivered to anyone'

# TEST
start_test 'garbage expiration time'

fake_creds <<EOF
access-nobody@example.com: test-access
expire-nobody@example.com: 99999999999999999999999999999999
EOF

test_send_only_fakesmtp 'post: error loading cred file: invalid expiration time
send: message not delivered to anyone'

# TEST
start_test 'refresh response has no access token'

fake_creds <<EOF
refresh-nobody@example.com: test-refresh
EOF

expect_http_post_refresh

fake_json_response <<EOF
{
  "refresh_token": "refresh-token",
  "token_type": "Bearer"
}
EOF

test_send 'post: error refreshing OAuth2 token
post: invalid response: no access token
send: message not delivered to anyone'

# TEST
start_test 'expired access token, no refresh token -- tell user to mhlogin'

fake_creds <<EOF
access-nobody@example.com: test-access
expire-nobody@example.com: 1414303986
EOF

test_send_only_fakesmtp 'post: no valid credentials -- run mhlogin -saslmech xoauth2 -authservice test
send: message not delivered to anyone'

# TEST
start_test 'access token has no expiration, no refresh token -- tell user to mhlogin'

fake_creds <<EOF
access-nobody@example.com: test-access
EOF

test_send_only_fakesmtp 'post: no valid credentials -- run mhlogin -saslmech xoauth2 -authservice test
send: message not delivered to anyone'

# TEST
start_test 'refresh finds no http server'

fake_creds <<EOF
access-nobody@example.com: test-access
refresh-nobody@example.com: test-refresh
EOF

cat > "${testname}.expected-send-output" <<EOF
post: error refreshing OAuth2 token
post: error making HTTP request to OAuth2 authorization endpoint: [details]
send: message not delivered to anyone
EOF

start_fakesmtp
run_prog send -draft -server 127.0.0.1 -port ${smtp_port} \
  -sasl -saslmech xoauth2 -authservice test -user nobody@example.com > "${testname}.send-output" 2>&1 || true
# Clear out an error message we get from libcurl on some systems (seen at least
# 3 different versions of this error message, on FreeBSD 10.1, Ubuntu 12.04, and
# Ubuntu 14.04).
f="${testname}.send-output"
sed 's/\(post: error making HTTP request to OAuth2 authorization endpoint:\).*/\1 [details]/' "$f" > "$f".clean
check "$f".clean "${testname}.expected-send-output"
rm "$f"

# TEST
start_test 'refresh gets bogus 200 response from http server'

expect_http_post_refresh

fake_http_response '200 OK' <<EOF
Content-Type: text/html

<html>doh!</htmxl>
EOF

test_send 'post: error refreshing OAuth2 token
post: invalid response
send: message not delivered to anyone'

# TEST
start_test 'refresh gets 500 response from http server'

expect_http_post_refresh

fake_http_response '500 Server Error' <<EOF
Content-Type: text/html

<html>doh!</html>
EOF

test_send 'post: error refreshing OAuth2 token
post: invalid response
send: message not delivered to anyone'

# TEST
start_test 'refresh gets proper error from http'

expect_http_post_refresh

fake_http_response '400 Bad Request' <<EOF
Content-Type: application/json

{
  "error": "invalid_grant"
}
EOF

test_send 'post: credentials rejected -- run mhlogin -saslmech xoauth2 -authservice test
send: message not delivered to anyone'

# TEST
start_test 'refresh gets response too big'

fake_creds <<EOF
refresh-nobody@example.com: test-refresh
EOF

expect_http_post_refresh

fake_json_response <<EOF
{
  "access_token": "test-access",
  "token_type": "Bearer",
  "expires_in": 3600
}
EOF

awk 'BEGIN { for (i = 0; i < 8192; i++) { print "." } }' \
    >> "${testname}.http-res"

test_send 'post: error refreshing OAuth2 token
post: refusing to process response body larger than 8192 bytes
send: message not delivered to anyone'

# TEST
start_test 'smtp server rejects token'

XOAUTH='not-that-one'

fake_creds <<EOF
access-nobody@example.com: test-access
expire-nobody@example.com: 2000000000
EOF

test_send_only_fakesmtp 'post: problem initializing server; [BHST] Authentication failed: Not no way, not no how!
send: message not delivered to anyone'

# TEST
start_test 'botched json response'

fake_creds <<EOF
refresh-nobody@example.com: test-refresh
EOF

expect_http_post_refresh

fake_json_response <<EOF
{
  "refresh_token": "refresh-toke
}
EOF

test_send 'post: error refreshing OAuth2 token
post: invalid response
send: message not delivered to anyone'

# TEST
start_test "smtp server doesn't support oauth"

unset XOAUTH

test_send_only_fakesmtp 'post: problem initializing server; [BHST] SMTP server does not support SASL
send: message not delivered to anyone'

clean_fakesmtp
clean_fakehttp
finish_test

exit ${failed:-0}
