1#!/usr/bin/env python 2# 3# Copyright 2014 Google Inc. All Rights Reserved. 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Tests for errors handling 18""" 19from __future__ import absolute_import 20 21__author__ = "afshar@google.com (Ali Afshar)" 22 23 24import unittest 25import httplib2 26 27 28from googleapiclient.errors import HttpError 29 30 31JSON_ERROR_CONTENT = b""" 32{ 33 "error": { 34 "errors": [ 35 { 36 "domain": "global", 37 "reason": "required", 38 "message": "country is required", 39 "locationType": "parameter", 40 "location": "country" 41 } 42 ], 43 "code": 400, 44 "message": "country is required", 45 "details": "error details" 46 } 47} 48""" 49 50JSON_ERROR_CONTENT_NO_DETAIL = b""" 51{ 52 "error": { 53 "errors": [ 54 { 55 "domain": "global", 56 "reason": "required", 57 "message": "country is required", 58 "locationType": "parameter", 59 "location": "country" 60 } 61 ], 62 "code": 400, 63 "message": "country is required" 64 } 65} 66""" 67 68 69def fake_response(data, headers, reason="Ok"): 70 response = httplib2.Response(headers) 71 response.reason = reason 72 return response, data 73 74 75class Error(unittest.TestCase): 76 """Test handling of error bodies.""" 77 78 def test_json_body(self): 79 """Test a nicely formed, expected error response.""" 80 resp, content = fake_response( 81 JSON_ERROR_CONTENT, 82 {"status": "400", "content-type": "application/json"}, 83 reason="Failed", 84 ) 85 error = HttpError(resp, content, uri="http://example.org") 86 self.assertEqual(error.error_details, "error details") 87 self.assertEqual(error.status_code, 400) 88 self.assertEqual( 89 str(error), 90 '<HttpError 400 when requesting http://example.org returned "country is required". Details: "error details">', 91 ) 92 93 def test_bad_json_body(self): 94 """Test handling of bodies with invalid json.""" 95 resp, content = fake_response( 96 b"{", {"status": "400", "content-type": "application/json"}, reason="Failed" 97 ) 98 error = HttpError(resp, content) 99 self.assertEqual(str(error), '<HttpError 400 when requesting None returned "Failed". Details: "{">') 100 101 def test_with_uri(self): 102 """Test handling of passing in the request uri.""" 103 resp, content = fake_response( 104 b"{", 105 {"status": "400", "content-type": "application/json"}, 106 reason="Failure", 107 ) 108 error = HttpError(resp, content, uri="http://example.org") 109 self.assertEqual( 110 str(error), 111 '<HttpError 400 when requesting http://example.org returned "Failure". Details: "{">', 112 ) 113 114 def test_missing_message_json_body(self): 115 """Test handling of bodies with missing expected 'message' element.""" 116 resp, content = fake_response( 117 b"{}", 118 {"status": "400", "content-type": "application/json"}, 119 reason="Failed", 120 ) 121 error = HttpError(resp, content) 122 self.assertEqual(str(error), '<HttpError 400 "Failed">') 123 124 def test_non_json(self): 125 """Test handling of non-JSON bodies""" 126 resp, content = fake_response(b"Invalid request", {"status": "400"}) 127 error = HttpError(resp, content) 128 self.assertEqual(str(error), '<HttpError 400 when requesting None returned "Ok". Details: "Invalid request">') 129 130 def test_missing_reason(self): 131 """Test an empty dict with a missing resp.reason.""" 132 resp, content = fake_response(b"}NOT OK", {"status": "400"}, reason=None) 133 error = HttpError(resp, content) 134 self.assertEqual(str(error), '<HttpError 400 when requesting None returned "". Details: "}NOT OK">') 135 136 def test_error_detail_for_missing_message_in_error(self): 137 """Test handling of data with missing 'details' or 'detail' element.""" 138 resp, content = fake_response( 139 JSON_ERROR_CONTENT_NO_DETAIL, 140 {"status": "400", "content-type": "application/json"}, 141 reason="Failed", 142 ) 143 error = HttpError(resp, content) 144 expected_error_details = "[{'domain': 'global', 'reason': 'required', 'message': 'country is required', 'locationType': 'parameter', 'location': 'country'}]" 145 self.assertEqual(str(error), '<HttpError 400 when requesting None returned "country is required". Details: "%s">' % expected_error_details) 146 self.assertEqual(str(error.error_details), expected_error_details) 147