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 <
[email protected]> 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 <
> [email protected]> wrote:
>
>>
>>
>> On Sat, Dec 9, 2017 at 11:50 AM, Harshal Dhumal <
>> [email protected]> wrote:
>>
>>>
>>> On Sat, Dec 9, 2017 at 11:30 AM, Dave Page <[email protected]> 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 <
>>>> [email protected]> 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 <[email protected]> wrote:
>>>>>
>>>>>> Murtuza, can you investigate please?
>>>>>>
>>>>>> Thanks!
>>>>>>
>>>>>> On Fri, Dec 8, 2017 at 8:08 PM, Bartosz Dmytrak <[email protected]>
>>>>>> 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: