Path: blob/develop/tests/unit/output/test_table_formatter.py
1567 views
# Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.1#2# Licensed under the Apache License, Version 2.0 (the "License"). You3# may not use this file except in compliance with the License. A copy of4# the License is located at5#6# http://aws.amazon.com/apache2.0/7#8# or in the "license" file accompanying this file. This file is9# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF10# ANY KIND, either express or implied. See the License for the specific11# language governing permissions and limitations under the License.12import unittest1314from awscli.formatter import TableFormatter15from awscli.table import MultiTable, Styler16from awscli.compat import StringIO1718SIMPLE_LIST = {19"QueueUrls": [20"https://us-west-2.queue.amazonaws.com/1/queue1",21"https://us-west-2.queue.amazonaws.com/1/queue2",22"https://us-west-2.queue.amazonaws.com/1/queue3",23"https://us-west-2.queue.amazonaws.com/1/queue4"24]25}26272829SIMPLE_LIST_TABLE = """\30------------------------------------------------------31| OperationName |32+----------------------------------------------------+33|| QueueUrls ||34|+--------------------------------------------------+|35|| https://us-west-2.queue.amazonaws.com/1/queue1 ||36|| https://us-west-2.queue.amazonaws.com/1/queue2 ||37|| https://us-west-2.queue.amazonaws.com/1/queue3 ||38|| https://us-west-2.queue.amazonaws.com/1/queue4 ||39|+--------------------------------------------------+|40"""4142SIMPLE_DICT = {"Attributes":43{"a": "0",44"b": "345600",45"c": "0",46"d": "65536",47"e": "1351044153",48"f": "0"}49}505152SIMPLE_DICT_TABLE = """\53----------------------------------------------------54| OperationName |55+--------------------------------------------------+56|| Attributes ||57|+---+---------+----+--------+--------------+-----+|58|| a | b | c | d | e | f ||59|+---+---------+----+--------+--------------+-----+|60|| 0| 345600 | 0 | 65536 | 1351044153 | 0 ||61|+---+---------+----+--------+--------------+-----+|62"""636465LIST_OF_DICTS = {66"OrderableDBInstanceOptions": [67{68"AvailabilityZones": [69{70"Name": "us-east-1a",71"ProvisionedIopsCapable": False72},73{74"Name": "us-east-1d",75"ProvisionedIopsCapable": True76}77],78"DBInstanceClass": "db.m1.large",79"Engine": "mysql",80"EngineVersion": "5.1.45",81"LicenseModel": "general-public-license",82"MultiAZCapable": True,83"ReadReplicaCapable": True,84"Vpc": False85},86{87"AvailabilityZones": [88{89"Name": "us-west-2a",90"ProvisionedIopsCapable": True91},92{93"Name": "us-west-2b",94"ProvisionedIopsCapable": True95}96],97"DBInstanceClass": "db.m1.xlarge",98"Engine": "mysql",99"EngineVersion": "5.1.57",100"LicenseModel": "general-public-license",101"MultiAZCapable": True,102"ReadReplicaCapable": True,103"Vpc": False104},105{106"AvailabilityZones": [107{108"Name": "us-west-2a",109"ProvisionedIopsCapable": True110},111],112"DBInstanceClass": "db.m1.xlarge",113"Engine": "mysql",114"EngineVersion": "5.1.57",115"LicenseModel": "general-public-license",116"MultiAZCapable": True,117"ReadReplicaCapable": True,118"Vpc": True119}120]121}122123LIST_OF_DICTS_TABLE = """\124-----------------------------------------------------------------------------------------------------------------------------125| OperationName |126+---------------------------------------------------------------------------------------------------------------------------+127|| OrderableDBInstanceOptions ||128|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|129|| DBInstanceClass | Engine | EngineVersion | LicenseModel | MultiAZCapable | ReadReplicaCapable | Vpc ||130|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|131|| db.m1.large | mysql | 5.1.45 | general-public-license | True | True | False ||132|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|133||| AvailabilityZones |||134||+----------------------------------------+------------------------------------------------------------------------------+||135||| Name | ProvisionedIopsCapable |||136||+----------------------------------------+------------------------------------------------------------------------------+||137||| us-east-1a | False |||138||| us-east-1d | True |||139||+----------------------------------------+------------------------------------------------------------------------------+||140|| OrderableDBInstanceOptions ||141|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|142|| DBInstanceClass | Engine | EngineVersion | LicenseModel | MultiAZCapable | ReadReplicaCapable | Vpc ||143|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|144|| db.m1.xlarge | mysql | 5.1.57 | general-public-license | True | True | False ||145|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|146||| AvailabilityZones |||147||+----------------------------------------+------------------------------------------------------------------------------+||148||| Name | ProvisionedIopsCapable |||149||+----------------------------------------+------------------------------------------------------------------------------+||150||| us-west-2a | True |||151||| us-west-2b | True |||152||+----------------------------------------+------------------------------------------------------------------------------+||153|| OrderableDBInstanceOptions ||154|+-----------------+---------+----------------+--------------------------+-----------------+----------------------+--------+|155|| DBInstanceClass | Engine | EngineVersion | LicenseModel | MultiAZCapable | ReadReplicaCapable | Vpc ||156|+-----------------+---------+----------------+--------------------------+-----------------+----------------------+--------+|157|| db.m1.xlarge | mysql | 5.1.57 | general-public-license | True | True | True ||158|+-----------------+---------+----------------+--------------------------+-----------------+----------------------+--------+|159||| AvailabilityZones |||160||+----------------------------------------+------------------------------------------------------------------------------+||161||| Name | ProvisionedIopsCapable |||162||+----------------------------------------+------------------------------------------------------------------------------+||163||| us-west-2a | True |||164||+----------------------------------------+------------------------------------------------------------------------------+||165"""166167168# First record has "Tags" scalar, second record does not.169INNER_LIST = {170"Snapshots": [171{172"Description": "TestVolume1",173"Tags": [{"Value": "TestVolume", "Key": "Name"}],174"VolumeId": "vol-12345",175"State": "completed",176"VolumeSize": 8,177"Progress": "100%",178"StartTime": "2012-05-23T21:46:41.000Z",179"SnapshotId": "snap-1234567",180"OwnerId": "12345"181},182{183"Description": "Created by CreateImage(i-1234) for ami-1234 from vol-1234",184"VolumeId": "vol-e543b98b",185"State": "completed",186"VolumeSize": 8,187"Progress": "100%",188"StartTime": "2012-05-25T00:07:20.000Z",189"SnapshotId": "snap-23456",190"OwnerId": "12345"191}192]193}194195INNER_LIST_TABLE = """\196-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------197| OperationName |198+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+199|| Snapshots ||200|+-------------------+--------------+----------------+---------------------+--------------------------------------+-----------------+-----------------+--------------------+|201|| Description | OwnerId | Progress | SnapshotId | StartTime | State | VolumeId | VolumeSize ||202|+-------------------+--------------+----------------+---------------------+--------------------------------------+-----------------+-----------------+--------------------+|203|| TestVolume1 | 12345 | 100% | snap-1234567 | 2012-05-23T21:46:41.000Z | completed | vol-12345 | 8 ||204|+-------------------+--------------+----------------+---------------------+--------------------------------------+-----------------+-----------------+--------------------+|205||| Tags |||206||+-----------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+||207||| Key | Value |||208||+-----------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+||209||| Name | TestVolume |||210||+-----------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+||211|| Snapshots ||212|+------------------------------------------------------------+----------+-----------+-------------+---------------------------+------------+---------------+--------------+|213|| Description | OwnerId | Progress | SnapshotId | StartTime | State | VolumeId | VolumeSize ||214|+------------------------------------------------------------+----------+-----------+-------------+---------------------------+------------+---------------+--------------+|215|| Created by CreateImage(i-1234) for ami-1234 from vol-1234 | 12345 | 100% | snap-23456 | 2012-05-25T00:07:20.000Z | completed | vol-e543b98b | 8 ||216|+------------------------------------------------------------+----------+-----------+-------------+---------------------------+------------+---------------+--------------+|217"""218219LIST_WITH_MISSING_KEYS = {220"Snapshots": [221{222"Description": "TestVolume1",223"Tags": "foo",224"VolumeId": "vol-12345",225"State": "completed",226"VolumeSize": 8,227"Progress": "100%",228"StartTime": "2012-05-23T21:46:41.000Z",229"SnapshotId": "snap-1234567",230"OwnerId": "12345"231},232{233"Description": "description",234"VolumeId": "vol-e543b98b",235"State": "completed",236"VolumeSize": 8,237"Progress": "100%",238"StartTime": "2012-05-25T00:07:20.000Z",239"SnapshotId": "snap-23456",240"OwnerId": "12345"241}242]243}244245LIST_WITH_MISSING_KEYS_TABLE = """\246-----------------------------------------------------------------------------------------------------------------------------------------247| OperationName |248+---------------------------------------------------------------------------------------------------------------------------------------+249|| Snapshots ||250|+-------------+----------+-----------+---------------+---------------------------+------------+-------+----------------+--------------+|251|| Description | OwnerId | Progress | SnapshotId | StartTime | State | Tags | VolumeId | VolumeSize ||252|+-------------+----------+-----------+---------------+---------------------------+------------+-------+----------------+--------------+|253|| TestVolume1| 12345 | 100% | snap-1234567 | 2012-05-23T21:46:41.000Z | completed | foo | vol-12345 | 8 ||254|| description| 12345 | 100% | snap-23456 | 2012-05-25T00:07:20.000Z | completed | | vol-e543b98b | 8 ||255|+-------------+----------+-----------+---------------+---------------------------+------------+-------+----------------+--------------+|256"""257258KEYS_NOT_FROM_FIRST_ROW = {259"Snapshots": [260{261"Description": "TestVolume1",262"Tags": "foo",263"VolumeId": "vol-12345",264"State": "completed",265"VolumeSize": 8,266"Progress": "100%",267"StartTime": "start_time",268# Missing EndTime.269"SnapshotId": "snap-1234567",270"OwnerId": "12345"271},272{273"Description": "description",274"State": "completed",275"VolumeSize": 8,276"Progress": "100%",277# Missing StartTime278"EndTime": "end_time",279"SnapshotId": "snap-23456",280"OwnerId": "12345"281}282]283}284285KEYS_NOT_FROM_FIRST_ROW_TABLE = """\286------------------------------------------------------------------------------------------------------------------------------------287| OperationName |288+----------------------------------------------------------------------------------------------------------------------------------+289|| Snapshots ||290|+-------------+-----------+----------+-----------+---------------+-------------+------------+-------+-------------+--------------+|291|| Description | EndTime | OwnerId | Progress | SnapshotId | StartTime | State | Tags | VolumeId | VolumeSize ||292|+-------------+-----------+----------+-----------+---------------+-------------+------------+-------+-------------+--------------+|293|| TestVolume1| | 12345 | 100% | snap-1234567 | start_time | completed | foo | vol-12345 | 8 ||294|| description| end_time | 12345 | 100% | snap-23456 | | completed | | | 8 ||295|+-------------+-----------+----------+-----------+---------------+-------------+------------+-------+-------------+--------------+|296"""297298JMESPATH_FILTERED_RESPONSE = [299[300[301"i-12345",302"ami-12345",303"ebs",304"t1.micro",305"running",306"disabled",307"util"308]309],310[311[312"i-56789",313"ami-56789",314"ebs",315"c1.medium",316"running",317"disabled",318"myname"319]320],321]322JMESPATH_FILTERED_RESPONSE_TABLE = """\323-------------------------------------------------------------------------------324| OperationName |325+---------+------------+------+------------+----------+------------+----------+326| i-12345| ami-12345 | ebs | t1.micro | running | disabled | util |327| i-56789| ami-56789 | ebs | c1.medium | running | disabled | myname |328+---------+------------+------+------------+----------+------------+----------+329"""330331332JMESPATH_FILTERED_RESPONSE_DICT = [333[334{335"InstanceId": "i-12345",336"RootDeviceType": "ebs",337"InstanceType": "t1.micro",338"ImageId": "ami-12345"339}340],341[342{343"InstanceId": "i-56789",344"RootDeviceType": "ebs",345"InstanceType": "c1.medium",346"ImageId": "ami-56789"347}348],349]350351352JMESPATH_FILTERED_RESPONSE_DICT_TABLE = """\353---------------------------------------------------------------354| OperationName |355+-----------+-------------+----------------+------------------+356| ImageId | InstanceId | InstanceType | RootDeviceType |357+-----------+-------------+----------------+------------------+358| ami-12345| i-12345 | t1.micro | ebs |359| ami-56789| i-56789 | c1.medium | ebs |360+-----------+-------------+----------------+------------------+361"""362363364class Object(object):365def __init__(self, **kwargs):366self.__dict__.update(kwargs)367self.query = None368369370class TestTableFormatter(unittest.TestCase):371maxDiff = None372373def setUp(self):374styler = Styler()375self.table = MultiTable(initial_section=False,376column_separator='|', styler=styler,377auto_reformat=False)378self.formatter = TableFormatter(Object(color='off'))379self.formatter.table = self.table380self.stream = StringIO()381382def assert_data_renders_to(self, data, table):383self.formatter('OperationName', data, stream=self.stream)384rendered = self.stream.getvalue()385if rendered != table:386error_message = ['Expected table rendering does not match '387'the actual table rendering:']388error_message.append('Expected:')389error_message.append(table)390error_message.append('Actual:')391error_message.append(rendered)392self.fail('\n'.join(error_message))393394def test_list_table(self):395self.assert_data_renders_to(data=SIMPLE_LIST, table=SIMPLE_LIST_TABLE)396397def test_dict_table(self):398self.assert_data_renders_to(data=SIMPLE_DICT, table=SIMPLE_DICT_TABLE)399400def test_list_of_dicts(self):401self.assert_data_renders_to(data=LIST_OF_DICTS,402table=LIST_OF_DICTS_TABLE)403404def test_inner_table(self):405self.assert_data_renders_to(data=INNER_LIST,406table=INNER_LIST_TABLE)407408def test_empty_table(self):409self.assert_data_renders_to(data={},410table='')411412def test_missing_keys(self):413self.assert_data_renders_to(data=LIST_WITH_MISSING_KEYS,414table=LIST_WITH_MISSING_KEYS_TABLE)415416def test_new_keys_after_first_row(self):417self.assert_data_renders_to(data=KEYS_NOT_FROM_FIRST_ROW,418table=KEYS_NOT_FROM_FIRST_ROW_TABLE)419420def test_jmespath_filtered_response(self):421self.assert_data_renders_to(data=JMESPATH_FILTERED_RESPONSE,422table=JMESPATH_FILTERED_RESPONSE_TABLE)423424def test_jmespath_filtered_dict_response(self):425self.assert_data_renders_to(data=JMESPATH_FILTERED_RESPONSE_DICT,426table=JMESPATH_FILTERED_RESPONSE_DICT_TABLE)427428429