Hi, Please find attached patch for various data type test cases.
-- *Harshal Dhumal* *Sr. Software Engineer* EnterpriseDB India: http://www.enterprisedb.com The Enterprise PostgreSQL Company On Mon, Dec 11, 2017 at 5:24 PM, Harshal Dhumal < harshal.dhu...@enterprisedb.com> wrote: > > -- > *Harshal Dhumal* > *Sr. Software Engineer* > > EnterpriseDB India: http://www.enterprisedb.com > The Enterprise PostgreSQL Company > > On Sat, Dec 9, 2017 at 12:06 PM, Khushboo Vashi < > khushboo.va...@enterprisedb.com> wrote: > >> >> >> On Sat, Dec 9, 2017 at 11:50 AM, Harshal Dhumal < >> harshal.dhu...@enterprisedb.com> wrote: >> >>> >>> On Sat, Dec 9, 2017 at 11:30 AM, Dave Page <dp...@pgadmin.org> wrote: >>> >>>> Hi >>>> >>>> Yeah, that one is in my list to work on. Have you specifically tested >>>> it with enum types (not enum[])? >>>> >>> >>> Yes. >>> >> >> @Harshal, >> >> Can you add multidimensional array, enum types into feature test >> (pg_datatype_validation_test.py) ? >> > > I think I need to add test cases for all array data types not just enum > types since fix was not targeted for any particular data type. > > >> >> [image: Inline image 3] >>> >>> >>> >>>> >>>> On Sat, Dec 9, 2017 at 5:55 AM, Harshal Dhumal < >>>> harshal.dhu...@enterprisedb.com> wrote: >>>> >>>>> Hi Dave, >>>>> >>>>> Recently I sent a patch >>>>> <https://www.postgresql.org/message-id/CAFiP3vzj6t2QuhkWy-sHnpcQB4tiq%2BK6gqLOVQkkcOuBtksvfw%40mail.gmail.com> >>>>> regarding multidimensional array representation issue. >>>>> In that patch I have reworked about how multidimensional (1 dimension >>>>> to n dimension) >>>>> array data should be represented in grid. >>>>> Also this patch covers almost all the array data types including >>>>> composite array data types like >>>>> int8range[], enum[], inet[], cidr[], macaddr[], uuid[], xml[], bit[], >>>>> varbit[] and so on. >>>>> >>>>> Please review the patch and let me know if any thing needs to be >>>>> included in this patch. >>>>> >>>>> Thanks, >>>>> >>>>> >>>>> -- >>>>> *Harshal Dhumal* >>>>> *Sr. Software Engineer* >>>>> >>>>> EnterpriseDB India: http://www.enterprisedb.com >>>>> The Enterprise PostgreSQL Company >>>>> >>>>> On Sat, Dec 9, 2017 at 10:45 AM, Dave Page <dp...@pgadmin.org> wrote: >>>>> >>>>>> Murtuza, can you investigate please? >>>>>> >>>>>> Thanks! >>>>>> >>>>>> On Fri, Dec 8, 2017 at 8:08 PM, Bartosz Dmytrak <bdmyt...@gmail.com> >>>>>> wrote: >>>>>> >>>>>>> Hi all, >>>>>>> >>>>>>> According to documentation: https://www.postgresql.org/doc >>>>>>> s/current/static/functions-enum.html when I execute SELECT >>>>>>> enum_range(null::rainbow) then output should look like this: >>>>>>> {red,orange,yellow,green,blue,purple} >>>>>>> >>>>>>> But in pgAdmin output looks like this: {{,r,e,d,,,o,r,a,n,g,e,,,y,e,l >>>>>>> ,l,o,w,,,g,r,e,e,n,,,b,l,u,e,,,p,u,r,p,l,e,}}. When you click on >>>>>>> the field, popup window shows correct value. I’ve double checked it in >>>>>>> psql, and output is correct. I think it could be considered as bug in >>>>>>> pgAdmin >>>>>>> >>>>>>> >>>>>>> >>>>>>> PgAdmin details: >>>>>>> >>>>>>> *Version *2.0 >>>>>>> >>>>>>> *Python Version *2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, >>>>>>> 20:42:59) [MSC v.1500 32 bit (Intel)] >>>>>>> >>>>>>> *Flask Version *0.12.2 >>>>>>> >>>>>>> *Application Mode *Desktop >>>>>>> >>>>>>> >>>>>>> >>>>>>> Pg Version: 10.1 >>>>>>> >>>>>>> Regardless this one, many thanks for your great job pgAdmin Team! >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> Best regards, >>>>>>> >>>>>>> *Bartosz Dmytrak* >>>>>>> >>>>>>> >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> Dave Page >>>>>> Blog: http://pgsnake.blogspot.com >>>>>> Twitter: @pgsnake >>>>>> >>>>>> EnterpriseDB UK: http://www.enterprisedb.com >>>>>> The Enterprise PostgreSQL Company >>>>>> >>>>> >>>>> >>>> >>>> >>>> -- >>>> Dave Page >>>> Blog: http://pgsnake.blogspot.com >>>> Twitter: @pgsnake >>>> >>>> EnterpriseDB UK: http://www.enterprisedb.com >>>> The Enterprise PostgreSQL Company >>>> >>> >>> >> >
diff --git a/web/pgadmin/feature_tests/datatype_test.json b/web/pgadmin/feature_tests/datatype_test.json new file mode 100644 index 0000000..49556b0 --- /dev/null +++ b/web/pgadmin/feature_tests/datatype_test.json @@ -0,0 +1,173 @@ +[ + { + "datatype": [ + "smallint", + "smallint", + "integer", + "integer", + "bigint", + "bigint", + "decimal", + "decimal", + "numeric", + "numeric", + "float[]", + "float[]", + "real", + "real[]", + "bytea", + "bytea[]" + ], + "input":[ + "-32767", + "32767", + "-2147483647", + "2147483647", + "-9223372036854775807", + "9223372036854775807", + "922337203685.4775807", + "92203685.477", + "922337203685.922337203685", + "-92233720368547758.08", + "ARRAY[1, 2, 3]", + "ARRAY['nan', 'nan', 'nan']", + "'Infinity'", + "'{Infinity}'", + "'E\\\\xDEADBEEF'", + "ARRAY['E\\\\xDEADBEEF', 'E\\\\xDEADBEEF']" + ], + "output":[ + "-32767", + "32767", + "-2147483647", + "2147483647", + "-9223372036854775807", + "9223372036854775807", + "922337203685.4775807", + "92203685.477", + "922337203685.922337203685", + "-92233720368547758.08", + "{1,2,3}", + "{NaN,NaN,NaN}", + "Infinity", + "{Infinity}", + "[binary data]", + "[binary data[]]" + ] + }, + { + "datatype": [ + "int4range", + "int8range", + "numrange", + "daterange", + "tsrange", + "tstzrange", + "int4range[]", + "int8range[]", + "numrange[]", + "daterange[]", + "tsrange[]", + "tstzrange[]", + "int8range[]", + "daterange[]", + "tstzrange[]", + "", + "" + ], + "input":[ + "'(1,2147483647)'", + "'(2,9223372036854775807)'", + "'(3,922337203685.922337203685]'", + "'(2010-01-01, 2010-02-01]'", + "'[2010-01-01 14:00, 2010-04-01 15:00)'", + "'[2010-01-01 14:00:00+05:30, 2010-06-01 15:00:00+05:30)'", + "'{\"(1,2147483647)\", \"(2,2147483647)\"}'", + "'{\"(2,9223372036854775807)\", \"(2,9223372036854775807)\"}'", + "'{\"(3,922337203685.922337203685]\", \"(5,922337203685.922337203685]\"}'", + "'{\"(2010-01-01, 2010-02-01]\", \"(2010-01-01, 2010-02-01]\"}'", + "'{\"[2010-01-01 14:00, 2010-04-01 15:00)\", \"[2010-01-01 14:00, 2010-04-01 15:00)\"}'", + "'{\"[2010-01-01 14:00:00+05:30, 2010-06-01 15:00:00+05:30)\", \"[2017-12-12 14:00:00+05:30, 2017-12-30 15:00:00+05:30)\"}'", + "'{{\"(2,9223372036854775807)\", \"(2,9223372036854775807)\"},{\"(2,9223372036854775807)\", \"(2,9223372036854775807)\"}}'", + "'{{\"(2010-01-01, 2010-02-01]\", \"(2010-01-01, 2010-02-01]\"},{\"(2010-01-01, 2010-02-01]\", \"(2010-01-01, 2010-02-01]\"}}'", + "'{{\"[2010-01-01 14:00:00+05:30, 2010-06-01 15:00:00+05:30)\", \"[2017-12-12 14:00:00+05:30, 2017-12-30 15:00:00+05:30)\"}, {\"[2010-01-01 14:00:00+05:30, 2010-06-01 15:00:00+05:30)\", \"[2017-12-12 14:00:00+05:30, 2017-12-30 15:00:00+05:30)\"}}'", + "enum_range(NULL::rainbow)", + "ARRAY[enum_range(NULL::rainbow), enum_range(NULL::rainbow)]" + ], + "output":[ + "[2,2147483647)", + "[3,9223372036854775807)", + "(3,922337203685.922337203685]", + "[2010-01-02,2010-02-02)", + "[\"2010-01-01 14:00:00\",\"2010-04-01 15:00:00\")", + "[\"2010-01-01 14:00:00+05:30\",\"2010-06-01 15:00:00+05:30\")", + "{\"[2,2147483647)\",\"[3,2147483647)\"}", + "{\"[3,9223372036854775807)\",\"[3,9223372036854775807)\"}", + "{\"(3,922337203685.922337203685]\",\"(5,922337203685.922337203685]\"}", + "{\"[2010-01-02,2010-02-02)\",\"[2010-01-02,2010-02-02)\"}", + "{\"[\\\"2010-01-01 14:00:00\\\",\\\"2010-04-01 15:00:00\\\")\",\"[\\\"2010-01-01 14:00:00\\\",\\\"2010-04-01 15:00:00\\\")\"}", + "{\"[\\\"2010-01-01 14:00:00+05:30\\\",\\\"2010-06-01 15:00:00+05:30\\\")\",\"[\\\"2017-12-12 14:00:00+05:30\\\",\\\"2017-12-30 15:00:00+05:30\\\")\"}", + "{{\"[3,9223372036854775807)\",\"[3,9223372036854775807)\"},{\"[3,9223372036854775807)\",\"[3,9223372036854775807)\"}}", + "{{\"[2010-01-02,2010-02-02)\",\"[2010-01-02,2010-02-02)\"},{\"[2010-01-02,2010-02-02)\",\"[2010-01-02,2010-02-02)\"}}", + "{{\"[\\\"2010-01-01 14:00:00+05:30\\\",\\\"2010-06-01 15:00:00+05:30\\\")\",\"[\\\"2017-12-12 14:00:00+05:30\\\",\\\"2017-12-30 15:00:00+05:30\\\")\"},{\"[\\\"2010-01-01 14:00:00+05:30\\\",\\\"2010-06-01 15:00:00+05:30\\\")\",\"[\\\"2017-12-12 14:00:00+05:30\\\",\\\"2017-12-30 15:00:00+05:30\\\")\"}}", + "{red,orange,yellow,green,blue,purple}", + "{{red,orange,yellow,green,blue,purple},{red,orange,yellow,green,blue,purple}}" + ] + }, + { + "datatype": [ + "inet", + "inet[]", + "inet[]", + "cidr", + "cidr[]", + "cidr[]", + "uuid", + "uuid[]", + "xml", + "xml[]", + "bit", + "bit[]", + "varbit", + "varbit[]", + "macaddr", + "macaddr[]" + ], + "input":[ + "'::2'", + "'{\"::2\",\"192.168.1.1/16\",\"FFF0:0:007a::\"}'", + "'{{\"::2\",\"192.168.1.1/16\",\"FFF0:0:007a::\"},{\"::2\",\"192.168.1.1/16\",\"FFF0:0:007a::\"}}'", + "'::1'", + "'{\"::1\", \"192.168.100.128/25\", \"FFF0:0:007a::\"}'", + "'{{\"::1\", \"192.168.100.128/25\", \"FFF0:0:007a::\"},{\"::1\", \"192.168.100.128/25\", \"FFF0:0:007a::\"}}'", + "'e1ab7b6d-a62d-4bee-b0ce-b8488f83d89c'", + "'{55f8e502-e0b4-11e7-80c1-9a214cf093ae, e1ab7b6d-a62d-4bee-b0ce-b8488f83d89c}'", + "'<?xml version=\"1.0\" encoding=\"UTF-8\"?><name>pgAdmin 4</name>'", + "'{\"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?><name>pgAdmin 4</name>\", \"<?xml version=\\\"1.0\\\" encoding=\\\"UTF-8\\\"?><name>pgAdmin 4</name>\"}'", + "'1'", + "'{0,1}'", + "'1001'", + "'{10010,1011}'", + "'08:00:2b:01:02:03'", + "'{08:00:2b:01:02:03, 08-00-2b-01-02-03, 08002b:010203, 08002b-010203, 0800.2b01.0203, 0800-2b01-0203, 08002b010203}'" + ], + "output":[ + "::2", + "{::2,192.168.1.1/16,fff0:0:7a::}", + "{{::2,192.168.1.1/16,fff0:0:7a::},{::2,192.168.1.1/16,fff0:0:7a::}}", + "::1/128", + "{::1/128,192.168.100.128/25,fff0:0:7a::/128}", + "{{::1/128,192.168.100.128/25,fff0:0:7a::/128},{::1/128,192.168.100.128/25,fff0:0:7a::/128}}", + "e1ab7b6d-a62d-4bee-b0ce-b8488f83d89c", + "{55f8e502-e0b4-11e7-80c1-9a214cf093ae,e1ab7b6d-a62d-4bee-b0ce-b8488f83d89c}", + "<name>pgAdmin 4</name>", + "{\"<name>pgAdmin 4</name>\",\"<name>pgAdmin 4</name>\"}", + "1", + "{0,1}", + "1001", + "{10010,1011}", + "08:00:2b:01:02:03", + "{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}" + ] + } +] \ No newline at end of file diff --git a/web/pgadmin/feature_tests/pg_datatype_validation_test.py b/web/pgadmin/feature_tests/pg_datatype_validation_test.py index 75993a4..70fd6cd 100644 --- a/web/pgadmin/feature_tests/pg_datatype_validation_test.py +++ b/web/pgadmin/feature_tests/pg_datatype_validation_test.py @@ -7,14 +7,26 @@ # ########################################################################## +import os +import json from selenium.common.exceptions import TimeoutException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By +from selenium.webdriver import ActionChains from regression.python_test_utils import test_utils from regression.feature_utils.base_feature_test import BaseFeatureTest +CURRENT_PATH = os.path.dirname(os.path.realpath(__file__)) + +try: + with open(CURRENT_PATH + '/datatype_test.json') as data_file: + config_data = json.load(data_file) +except Exception as e: + print(str(e)) + + class PGDataypeFeatureTest(BaseFeatureTest): """ This feature test will test the different Postgres @@ -35,6 +47,55 @@ class PGDataypeFeatureTest(BaseFeatureTest): test_utils.drop_database(connection, "acceptance_test_db") test_utils.create_database(self.server, "acceptance_test_db") + # For this test case we need to set "Insert bracket pairs?" + # SQL Editor preference to 'false' to avoid codemirror + # to add matching closing bracket by it self. + self._update_preferences() + + def _update_preferences(self): + self.page.find_by_id("mnu_file").click() + self.page.find_by_id("mnu_preferences").click() + wait = WebDriverWait(self.page.driver, 10) + + wait.until(EC.presence_of_element_located( + (By.XPATH, "//*[contains(string(), 'Show system objects?')]")) + ) + + self.page.find_by_css_selector(".ajs-maximize").click() + + sql_editor = self.page.find_by_xpath( + "//*[contains(@class,'aciTreeLi') and contains(.,'SQL Editor')]") + + sql_editor.find_element_by_xpath( + "//*[contains(@class,'aciTreeText') and contains(.,'Options')]")\ + .click() + + insert_bracket_pairs_control= self.page.find_by_xpath( + "//div[contains(@class,'pgadmin-control-group') and contains(.,'Insert bracket pairs?')]") + + switch_btn = insert_bracket_pairs_control.\ + find_element_by_class_name('bootstrap-switch') + + # check if switch is on then only toggle. + if 'bootstrap-switch-on' in switch_btn.get_attribute('class'): + switch_btn.click() + + # save and close the preference dialog. + self.page.find_by_xpath( + "//*[contains(@class,'btn-primary') and contains(.,'OK')]").click() + + self.page.wait_for_element_to_disappear( + lambda driver: driver.find_element_by_css_selector(".ajs-modal") + ) + + def _create_enum_type(self): + query = """CREATE TYPE public.rainbow AS ENUM ('red', 'orange', + 'yellow','green','blue','purple'); + """ + self.page.fill_codemirror_area_with(query) + self.page.find_by_id("btn-flash").click() + self._clear_query_tool() + def runTest(self): self.page.wait_for_spinner_to_disappear() self.page.add_server(self.server) @@ -60,59 +121,79 @@ class PGDataypeFeatureTest(BaseFeatureTest): self.page.toggle_open_tree_item('acceptance_test_db') def _check_datatype(self): - query = r"SELECT -32767::smallint, 32767::smallint," \ - r"-2147483647::integer, 2147483647::integer," \ - r"9223372036854775807::bigint, 9223372036854775807::bigint," \ - r"922337203685.4775807::decimal, 92203685.477::decimal," \ - r"922337203685.922337203685::numeric, " \ - r"-92233720368547758.08::numeric," \ - r"ARRAY[1, 2, 3]::float[], ARRAY['nan', 'nan', 'nan']::float[]," \ - r"'Infinity'::real, '{Infinity}'::real[]," \ - r"E'\\xDEADBEEF'::bytea, ARRAY[E'\\xDEADBEEF', E'\\xDEADBEEF']::bytea[];" - - expected_output = [ - '-32767', '32767', '-2147483647', '2147483647', - '9223372036854775807', '9223372036854775807', - '922337203685.4775807', '92203685.477', - '922337203685.922337203685', '-92233720368547758.08', - '{1,2,3}', '{NaN,NaN,NaN}', - 'Infinity', '{Infinity}', - 'binary data', 'binary data[]' - ] - + # Slick grid does not render all the column if viewport is not enough + # wide. So execute test as batch of queries. self.page.open_query_tool() - self.page.fill_codemirror_area_with(query) - self.page.find_by_id("btn-flash").click() - wait = WebDriverWait(self.page.driver, 5) + self._create_enum_type() + for batch in config_data: + query = self.construct_select_query(batch) + self.page.fill_codemirror_area_with(query) + self.page.find_by_id("btn-flash").click() + wait = WebDriverWait(self.page.driver, 5) + + wait.until(EC.presence_of_element_located( + (By.XPATH, + "//*[contains(@class,'column-type') and contains(.,'{}')]".format(batch['datatype'][0]) + )) + ) - canvas = wait.until(EC.presence_of_element_located( - (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")) - ) + canvas = wait.until(EC.presence_of_element_located( + (By.CSS_SELECTOR, "#datagrid .slick-viewport .grid-canvas")) + ) - # For every sample data-type value, check the expected output. - cnt = 2 - cells = canvas.find_elements_by_css_selector('.slick-cell') - # remove first element as it is row number. - cells.pop(0) - for val, cell in zip(expected_output, cells): - try: - source_code = cell.text - - PGDataypeFeatureTest.check_result( - source_code, - expected_output[cnt - 2] - ) - cnt += 1 - except TimeoutException: - assert False, "{0} does not match with {1}".format( - val, expected_output[cnt] - ) + # For every sample data-type value, check the expected output. + cnt = 2 + cells = canvas.find_elements_by_css_selector('.slick-cell') + # remove first element as it is row number. + cells.pop(0) + for val, cell, datatype in zip(batch['output'], cells, batch['datatype']): + try: + source_code = cell.text + PGDataypeFeatureTest.check_result( + datatype, + source_code, + batch['output'][cnt - 2] + ) + cnt += 1 + except TimeoutException: + assert False,\ + "for datatype {0}\n{1} does not match with {2}".format( + datatype, val, batch['output'][cnt] + ) + self._clear_query_tool() @staticmethod - def check_result(source_code, string_to_find): - assert source_code.find(string_to_find) != -1,\ - "{0} does not match with {1}".format( - source_code, string_to_find - ) + def construct_select_query(batch): + query = 'SELECT ' + first = True + for datatype, input in zip(batch['datatype'], batch['input']): + if datatype != '': + dataformatter = '{}::{}' + else: + dataformatter = '{}' + + if first: + query += dataformatter.format(input, datatype) + else: + query += ','+dataformatter.format(input, datatype) + first = False + return query + ';' + @staticmethod + def check_result(datatype, source_code, string_to_find): + assert source_code == string_to_find,\ + "for datatype {0}\n{1} does not match with {2}".format( + datatype, source_code, string_to_find + ) + def _clear_query_tool(self): + self.page.click_element( + self.page.find_by_xpath("//*[@id='btn-clear-dropdown']") + ) + ActionChains(self.driver)\ + .move_to_element(self.page.find_by_xpath("//*[@id='btn-clear']"))\ + .perform() + self.page.click_element( + self.page.find_by_xpath("//*[@id='btn-clear']") + ) + self.page.click_modal('Yes') diff --git a/web/regression/feature_utils/pgadmin_page.py b/web/regression/feature_utils/pgadmin_page.py index 26e10cd..255842f 100644 --- a/web/regression/feature_utils/pgadmin_page.py +++ b/web/regression/feature_utils/pgadmin_page.py @@ -226,6 +226,19 @@ class PgadminPage: return self._wait_for("element to exist", element_if_it_exists) + def wait_for_element_to_disappear(self, find_method_with_args): + def element_if_it_disappears(driver): + try: + element = find_method_with_args(driver) + if element.is_displayed() and element.is_enabled(): + return False + + return True + except NoSuchElementException: + return True + + return self._wait_for("element to disappear", element_if_it_disappears) + def wait_for_reloading_indicator_to_disappear(self): def reloading_indicator_has_disappeared(driver): try: