def setUp(self): self.output_stream = BytesIO() self.formatter = TextFormatter(self._COL_WIDTHS, self.output_stream) self.timestamp = 1511376242067 command_time = datetime.datetime.fromtimestamp(self.timestamp / 1000) self.formatted_time = datetime.datetime.strftime( command_time, '%Y-%m-%d %I:%M:%S %p')
def setUp(self): history_recorder = self._make_clean_history_recorder() super(BaseHistoryCommandParamsTest, self).setUp() self.history_recorder = history_recorder self.files = FileCreator() config_contents = ('[default]\n' 'cli_history = enabled') self.environ['AWS_CONFIG_FILE'] = self.files.create_file( 'config', config_contents) self.environ['AWS_CLI_HISTORY_FILE'] = self.files.create_file( 'history.db', '') self.driver = create_clidriver() # The run_cmd patches stdout with a StringIO object (similar to what # nose does). Therefore it will run into issues when # get_binary_stdout is called because it returns sys.stdout.buffer # for Py3 and StringIO does not have a buffer self.binary_stdout_patch = mock.patch('awscli.utils.get_binary_stdout') mock_get_binary_stdout = self.binary_stdout_patch.start() self.binary_stdout = BytesIO() mock_get_binary_stdout.return_value = self.binary_stdout
def setUp(self): self.output = BytesIO() self.formatter = DetailedFormatter(self.output, colorize=False)
class TestDetailedFormatter(unittest.TestCase): def setUp(self): self.output = BytesIO() self.formatter = DetailedFormatter(self.output, colorize=False) def get_pretty_xml(self, xml_str): xml_dom = xml.dom.minidom.parseString(xml_str) return xml_dom.toprettyxml(indent=' '*4, newl='\n') def assert_output(self, for_event, contains): self.formatter.display(for_event) collected_output = ensure_text_type(self.output.getvalue()) for line in contains: self.assertIn(line, collected_output) def test_display_cli_version(self): self.assert_output( for_event={ 'event_type': 'CLI_VERSION', 'id': 'my-id', 'payload': 'aws-cli/1.11.188', 'timestamp': 86400000, 'request_id': None }, contains=[ 'AWS CLI command entered', 'with AWS CLI version: aws-cli/1.11.188' ] ) def test_can_use_color(self): self.formatter = DetailedFormatter(self.output, colorize=True) self.assert_output( for_event={ 'event_type': 'CLI_VERSION', 'id': 'my-id', 'payload': 'aws-cli/1.11.188', 'timestamp': 86400000, 'request_id': None }, contains=[ '\x1b[1mAWS CLI command entered', '\x1b[36mwith AWS CLI version:' ] ) def test_display_cli_arguments(self): self.assert_output( for_event={ 'event_type': 'CLI_ARGUMENTS', 'id': 'my-id', 'payload': ['ec2', 'describe-regions'], 'timestamp': 86400000, 'request_id': None }, contains=[ "with arguments: ['ec2', 'describe-regions']" ] ) def test_display_api_call(self): self.assert_output( for_event={ 'event_type': 'API_CALL', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'service': 'ec2', 'operation': 'DescribeRegions', 'params': {} }, 'timestamp': 86400000, }, contains=[ 'to service: ec2\n', 'using operation: DescribeRegions\n', 'with parameters: {}\n' ] ) def test_two_different_api_calls_have_different_numbers(self): event = { 'event_type': 'API_CALL', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'service': 'ec2', 'operation': 'DescribeRegions', 'params': {} }, 'timestamp': 86400000, } self.formatter.display(event) collected_output = ensure_text_type(self.output.getvalue()) self.assertIn('[0] API call made', collected_output) other_event = { 'event_type': 'API_CALL', 'id': 'my-id', 'request_id': 'other-id', 'payload': { 'service': 'ec2', 'operation': 'DescribeRegions', 'params': {} }, 'timestamp': 86400000, } self.formatter.display(other_event) new_output = ensure_text_type(self.output.getvalue())[ len(collected_output):] self.assertIn('[1] API call made', new_output) def test_display_http_request(self): self.assert_output( for_event={ 'event_type': 'HTTP_REQUEST', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'method': 'GET', 'url': 'https://myservice.us-west-2.amazonaws.com', 'headers': {}, 'body': 'This is my body' }, 'timestamp': 86400000, }, contains=[ 'to URL: https://myservice.us-west-2.amazonaws.com\n', 'with method: GET\n', 'with headers: {}\n', 'with body: This is my body\n' ] ) def test_display_http_request_with_streaming_body(self): self.assert_output( for_event={ 'event_type': 'HTTP_REQUEST', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'method': 'GET', 'url': 'https://myservice.us-west-2.amazonaws.com', 'headers': {}, 'body': 'This should not be printed out', 'streaming': True }, 'timestamp': 86400000, }, contains=[ 'with body: The body is a stream and will not be displayed', ] ) def test_display_http_request_with_no_payload(self): self.assert_output( for_event={ 'event_type': 'HTTP_REQUEST', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'method': 'GET', 'url': 'https://myservice.us-west-2.amazonaws.com', 'headers': {}, 'body': None }, 'timestamp': 86400000, }, contains=[ 'with body: There is no associated body' ] ) def test_display_http_request_with_empty_string_payload(self): self.assert_output( for_event={ 'event_type': 'HTTP_REQUEST', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'method': 'GET', 'url': 'https://myservice.us-west-2.amazonaws.com', 'headers': {}, 'body': '' }, 'timestamp': 86400000, }, contains=[ 'with body: There is no associated body' ] ) def test_display_http_request_with_xml_payload(self): xml_body = '<?xml version="1.0" ?><foo><bar>text</bar></foo>' self.assert_output( for_event={ 'event_type': 'HTTP_REQUEST', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'method': 'GET', 'url': 'https://myservice.us-west-2.amazonaws.com', 'headers': {}, 'body': xml_body }, 'timestamp': 86400000, }, contains=[ 'with body: ' + self.get_pretty_xml(xml_body) ] ) def test_display_http_request_with_xml_payload_and_whitespace(self): xml_body = '<?xml version="1.0" ?><foo><bar>text</bar></foo>' self.assert_output( for_event={ 'event_type': 'HTTP_REQUEST', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'method': 'GET', 'url': 'https://myservice.us-west-2.amazonaws.com', 'headers': {}, 'body': self.get_pretty_xml(xml_body) }, 'timestamp': 86400000, }, # The XML should not be prettified more than once if the body # of the request was already prettied. contains=[ 'with body: ' + self.get_pretty_xml(xml_body) ] ) def test_display_http_request_with_json_struct_payload(self): self.assert_output( for_event={ 'event_type': 'HTTP_REQUEST', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'method': 'GET', 'url': 'https://myservice.us-west-2.amazonaws.com', 'headers': {}, 'body': '{"foo": "bar"}' }, 'timestamp': 86400000, }, contains=[ 'with body: {\n' ' "foo": "bar"\n' '}' ] ) def test_shares_api_number_across_events_of_same_api_call(self): self.assert_output( for_event={ 'event_type': 'API_CALL', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'service': 'ec2', 'operation': 'DescribeRegions', 'params': {} }, 'timestamp': 86400000, }, contains=[ '[0] API call made' ] ) self.assert_output( for_event={ 'event_type': 'HTTP_REQUEST', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'method': 'GET', 'url': 'https://myservice.us-west-2.amazonaws.com', 'headers': {}, 'body': 'This is my body' }, 'timestamp': 86400000, }, contains=[ '[0] HTTP request sent' ] ) def test_display_http_response(self): self.assert_output( for_event={ 'event_type': 'HTTP_RESPONSE', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'status_code': 200, 'headers': {}, 'body': 'This is my body' }, 'timestamp': 86400000, }, contains=[ '[0] HTTP response received', 'with status code: 200\n', 'with headers: {}\n', 'with body: This is my body\n' ] ) def test_display_http_response_with_streaming_body(self): self.assert_output( for_event={ 'event_type': 'HTTP_RESPONSE', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'status_code': 200, 'headers': {}, 'body': 'This should not be printed out', 'streaming': True }, 'timestamp': 86400000, }, contains=[ 'with body: The body is a stream and will not be displayed' ] ) def test_display_http_response_with_no_payload(self): self.assert_output( for_event={ 'event_type': 'HTTP_RESPONSE', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'status_code': 200, 'headers': {}, 'body': None }, 'timestamp': 86400000, }, contains=[ 'with body: There is no associated body' ] ) def test_display_http_response_with_empty_string_payload(self): self.assert_output( for_event={ 'event_type': 'HTTP_RESPONSE', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'status_code': 200, 'headers': {}, 'body': '' }, 'timestamp': 86400000, }, contains=[ 'with body: There is no associated body' ] ) def test_display_http_response_with_xml_payload(self): xml_body = '<?xml version="1.0" ?><foo><bar>text</bar></foo>' self.assert_output( for_event={ 'event_type': 'HTTP_RESPONSE', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'status_code': 200, 'headers': {}, 'body': xml_body }, 'timestamp': 86400000, }, contains=[ 'with body: ' + self.get_pretty_xml(xml_body) ] ) def test_display_http_response_with_xml_payload_and_whitespace(self): xml_body = '<?xml version="1.0" ?><foo><bar>text</bar></foo>' self.assert_output( for_event={ 'event_type': 'HTTP_RESPONSE', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'status_code': 200, 'headers': {}, 'body': self.get_pretty_xml(xml_body) }, 'timestamp': 86400000, }, # The XML should not be prettified more than once if the body # of the response was already prettied. contains=[ 'with body: ' + self.get_pretty_xml(xml_body) ] ) def test_display_http_response_with_json_struct_payload(self): self.assert_output( for_event={ 'event_type': 'HTTP_RESPONSE', 'id': 'my-id', 'request_id': 'some-id', 'payload': { 'status_code': 200, 'headers': {}, 'body': '{"foo": "bar"}' }, 'timestamp': 86400000, }, contains=[ 'with body: {\n', ' "foo": "bar"\n', '}', ] ) def test_display_parsed_response(self): self.assert_output( for_event={ 'event_type': 'PARSED_RESPONSE', 'id': 'my-id', 'request_id': 'some-id', 'payload': {}, 'timestamp': 86400000, }, contains=[ '[0] HTTP response parsed', 'parsed to: {}' ] ) def test_display_cli_rc(self): self.assert_output( for_event={ 'event_type': 'CLI_RC', 'id': 'my-id', 'payload': 0, 'timestamp': 86400000, 'request_id': None }, contains=[ 'AWS CLI command exited', 'with return code: 0' ] ) def test_display_unknown_type(self): event = { 'event_type': 'UNKNOWN', 'id': 'my-id', 'payload': 'foo', 'timestamp': 86400000, 'request_id': None } self.formatter.display(event) collected_output = ensure_text_type(self.output.getvalue()) self.assertEqual('', collected_output)
class TestTextFormatter(unittest.TestCase): _COL_WIDTHS = {'id_a': 10, 'timestamp': 23, 'args': 10, 'rc': 10} def setUp(self): self.output_stream = BytesIO() self.formatter = TextFormatter(self._COL_WIDTHS, self.output_stream) self.timestamp = 1511376242067 command_time = datetime.datetime.fromtimestamp(self.timestamp / 1000) self.formatted_time = datetime.datetime.strftime( command_time, '%Y-%m-%d %I:%M:%S %p') def _format_records(self, records): adapter = RecordAdapter(iter(records)) self.formatter(adapter) def test_can_emit_single_row(self): self._format_records([{ 'id_a': 'foo', 'timestamp': self.timestamp, 'args': '["s3", "ls"]', 'rc': 0 }]) expected_output = 'foo %s s3 ls 0\n' % self.formatted_time actual_output = ensure_text_type(self.output_stream.getvalue()) self.assertEqual(expected_output, actual_output) def test_can_emit_multiple_rows(self): self._format_records([{ 'id_a': 'foo', 'timestamp': self.timestamp, 'args': '["s3", "ls"]', 'rc': 0 }, { 'id_a': 'bar', 'timestamp': self.timestamp, 'args': '["s3", "cp"]', 'rc': 1 }]) expected_output = ('foo %s s3 ls 0\n' 'bar %s s3 cp 1\n') % ( self.formatted_time, self.formatted_time) actual_output = ensure_text_type(self.output_stream.getvalue()) self.assertEqual(expected_output, actual_output) def test_can_truncate_args(self): # Truncate the argument if it won't fit in the space alotted to the # arguments field. self._format_records([{ 'id_a': 'foo', 'timestamp': self.timestamp, 'args': ('["s3", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]'), 'rc': 0 }]) expected_output = 'foo %s s3 aaa... 0\n' % self.formatted_time actual_output = ensure_text_type(self.output_stream.getvalue()) self.assertEqual(expected_output, actual_output)
class TestTextFormatter(unittest.TestCase): _COL_WIDTHS = { 'id_a': 10, 'timestamp': 23, 'args': 10, 'rc': 10 } def setUp(self): self.output_stream = BytesIO() self.formatter = TextFormatter(self._COL_WIDTHS, self.output_stream) self.timestamp = 1511376242067 command_time = datetime.datetime.fromtimestamp(self.timestamp / 1000) self.formatted_time = datetime.datetime.strftime( command_time, '%Y-%m-%d %I:%M:%S %p') def _format_records(self, records): adapter = RecordAdapter(iter(records)) self.formatter(adapter) def test_can_emit_single_row(self): self._format_records([ { 'id_a': 'foo', 'timestamp': self.timestamp, 'args': '["s3", "ls"]', 'rc': 0 } ]) expected_output = 'foo %s s3 ls 0\n' % self.formatted_time actual_output = ensure_text_type(self.output_stream.getvalue()) self.assertEqual(expected_output, actual_output) def test_can_emit_multiple_rows(self): self._format_records([ { 'id_a': 'foo', 'timestamp': self.timestamp, 'args': '["s3", "ls"]', 'rc': 0 }, { 'id_a': 'bar', 'timestamp': self.timestamp, 'args': '["s3", "cp"]', 'rc': 1 } ]) expected_output = ('foo %s s3 ls 0\n' 'bar %s s3 cp 1\n') % ( self.formatted_time, self.formatted_time) actual_output = ensure_text_type(self.output_stream.getvalue()) self.assertEqual(expected_output, actual_output) def test_can_truncate_args(self): # Truncate the argument if it won't fit in the space alotted to the # arguments field. self._format_records([ { 'id_a': 'foo', 'timestamp': self.timestamp, 'args': ('["s3", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]'), 'rc': 0 } ]) expected_output = 'foo %s s3 aaa... 0\n' % self.formatted_time actual_output = ensure_text_type(self.output_stream.getvalue()) self.assertEqual(expected_output, actual_output)