#!/usr/bin/env python2.7
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Tests for google.apphosting.tools.devappserver2.api_server."""


import cStringIO
import tempfile
import unittest
import urllib
import wsgiref.util

from google.appengine.api import user_service_pb
from google.appengine.datastore import datastore_stub_util
from google.appengine.ext.remote_api import remote_api_pb
from google.appengine.tools.devappserver2 import api_server
from google.appengine.tools.devappserver2 import wsgi_request_info
from google.appengine.tools.devappserver2 import wsgi_test_utils

APP_ID = 'test'
APPLICATION_ROOT = '/tmp'
TRUSTED = False
_, BLOBSTORE_PATH = tempfile.mkstemp(prefix='ae-blobstore')
_, DATASTORE_PATH = tempfile.mkstemp(prefix='ae-datastore')
DATASTORE_REQUIRE_INDEXES = False
IMAGES_HOST_PREFIX = 'localhost:8080'
LOGS_PATH = ':memory:'
MAIL_SMTP_HOST = 'localhost'
MAIL_SMTP_PORT = 80
MAIL_SMTP_USER = 'user'
MAIL_SMTP_PASSWORD = 'abc123'
MAIL_ENABLE_SENDMAIL = False
MAIL_SHOW_MAIL_BODY = True
_, MATCHER_PROSPECTIVE_SEARCH_PATH = tempfile.mkstemp(prefix='ae-ps')
TASKQUEUE_AUTO_RUN_TASKS = False
TASKQUEUE_DEFAULT_HTTP_SERVER = 'localhost:8080'
USER_LOGIN_URL = 'https://localhost/Login?continue=%s'
USER_LOGOUT_URL = 'https://localhost/Logout?continue=%s'

request_data = wsgi_request_info.WSGIRequestInfo(None)


def setup_stubs():
  """Setup the API stubs. This can only be done once."""
  api_server.test_setup_stubs(
      request_data,
      app_id=APP_ID,
      application_root=APPLICATION_ROOT,
      trusted=TRUSTED,
      blobstore_path=BLOBSTORE_PATH,
      datastore_consistency=datastore_stub_util.TimeBasedHRConsistencyPolicy(),
      datastore_path=DATASTORE_PATH,
      datastore_require_indexes=DATASTORE_REQUIRE_INDEXES,
      images_host_prefix=IMAGES_HOST_PREFIX,
      logs_path=':memory:',
      mail_smtp_host=MAIL_SMTP_HOST,
      mail_smtp_port=MAIL_SMTP_PORT,
      mail_smtp_user=MAIL_SMTP_USER,
      mail_smtp_password=MAIL_SMTP_PASSWORD,
      mail_enable_sendmail=MAIL_ENABLE_SENDMAIL,
      mail_show_mail_body=MAIL_SHOW_MAIL_BODY,
      matcher_prospective_search_path=MATCHER_PROSPECTIVE_SEARCH_PATH,
      taskqueue_auto_run_tasks=TASKQUEUE_AUTO_RUN_TASKS,
      taskqueue_default_http_server=TASKQUEUE_DEFAULT_HTTP_SERVER,
      user_login_url=USER_LOGIN_URL,
      user_logout_url=USER_LOGOUT_URL)


class TestAPIServer(wsgi_test_utils.WSGITestCase):
  """Tests for api_server.APIServer."""

  def setUp(self):
    setup_stubs()
    self.server = api_server.APIServer('localhost',
                                       0,
                                       APP_ID)

  def tearDown(self):
    api_server.cleanup_stubs()

  def test_user_api_call(self):
    logout_response = user_service_pb.CreateLogoutURLRequest()
    logout_response.set_destination_url(
        USER_LOGOUT_URL % urllib.quote('http://machine:8080/crazy_logout'))

    expected_remote_response = remote_api_pb.Response()
    expected_remote_response.set_response(logout_response.Encode())

    logout_request = user_service_pb.CreateLogoutURLRequest()
    logout_request.set_destination_url('/crazy_logout')

    request_environ = {'HTTP_HOST': 'machine:8080'}
    wsgiref.util.setup_testing_defaults(request_environ)

    with request_data.request(request_environ, None) as request_id:
      remote_request = remote_api_pb.Request()
      remote_request.set_service_name('user')
      remote_request.set_method('CreateLogoutURL')
      remote_request.set_request(logout_request.Encode())
      remote_request.set_request_id(request_id)
      remote_payload = remote_request.Encode()

      environ = {'CONTENT_LENGTH': len(remote_payload),
                 'REQUEST_METHOD': 'POST',
                 'wsgi.input': cStringIO.StringIO(remote_payload)}

      expected_headers = {'Content-Type': 'application/octet-stream'}
      self.assertResponse('200 OK',
                          expected_headers,
                          expected_remote_response.Encode(),
                          self.server,
                          environ)

  def test_GET(self):
    environ = {'REQUEST_METHOD': 'GET',
               'QUERY_STRING': 'rtok=23'}
    self.assertResponse('200 OK',
                        {'Content-Type': 'text/plain'},
                        "{app_id: test, rtok: '23'}\n",
                        self.server,
                        environ)

if __name__ == '__main__':
  unittest.main()

