From ce7feed177396b70a2e903b0c1e2d606b6c99484 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Thu, 29 Feb 2024 17:30:12 -0800 Subject: [PATCH 1/7] Move extension tests to their own file They are slow and large and I usually don't actually care to run them when running ddl tests. --- tests/test_edgeql_ddl.py | 972 ------------------------------- tests/test_edgeql_extensions.py | 995 ++++++++++++++++++++++++++++++++ 2 files changed, 995 insertions(+), 972 deletions(-) create mode 100644 tests/test_edgeql_extensions.py diff --git a/tests/test_edgeql_ddl.py b/tests/test_edgeql_ddl.py index 21158394792..a7a02c7c3f1 100644 --- a/tests/test_edgeql_ddl.py +++ b/tests/test_edgeql_ddl.py @@ -18,7 +18,6 @@ import asyncio import decimal -import json import os import re import textwrap @@ -16180,977 +16179,6 @@ async def test_edgeql_ddl_no_tx_mig_error_03(self): insert Mig03 { n := {} }; ''') - -class TestDDLExtensions(tb.DDLTestCase): - TRANSACTION_ISOLATION = False - PARALLELISM_GRANULARITY = 'suite' - - async def _extension_test_01(self): - await self.con.execute(''' - create extension ltree - ''') - - await self.assert_query_result( - ''' - select ltree::nlevel( - 'foo.bar'); - ''', - [2], - ) - await self.assert_query_result( - ''' - select ( - 'foo.bar'); - ''', - ['foo.bar'], - ) - await self.assert_query_result( - ''' - select 'foo.bar'; - ''', - [['foo', 'bar']], - json_only=True, - ) - - await self.con.execute(''' - create type Foo { create property x -> ltree::ltree }; - insert Foo { x := 'foo.bar.baz' }; - ''') - - await self.assert_query_result( - ''' - select Foo.x; - ''', - [['foo', 'bar', 'baz']], - json_only=True, - ) - - await self.con.execute(''' - drop type Foo; - drop extension ltree; - ''') - - async def test_edgeql_ddl_extensions_01(self): - # Make an extension that wraps a tiny bit of the ltree package. - await self.con.execute(''' - create extension package ltree VERSION '1.0' { - set ext_module := "ltree"; - set sql_extensions := ["ltree >=1.0,<10.0"]; - create module ltree; - create scalar type ltree::ltree { - set sql_type := "ltree"; - }; - create cast from ltree::ltree to std::str { - SET volatility := 'Immutable'; - USING SQL CAST; - }; - create cast from std::str to ltree::ltree { - SET volatility := 'Immutable'; - USING SQL CAST; - }; - - # Use a non-trivial json representation just to show that we can. - create cast from ltree::ltree to std::json { - SET volatility := 'Immutable'; - USING SQL $$ - select to_jsonb(string_to_array("val"::text, '.')); - $$ - }; - create cast from std::json to ltree::ltree { - SET volatility := 'Immutable'; - USING SQL $$ - select string_agg(edgedb.raise_on_null( - edgedbstd."std|cast@std|json@std|str_f"(z.z), - 'invalid_parameter_value', 'invalid null value in cast'), - '.')::ltree - from unnest( - edgedbstd."std|cast@std|json@array_f"("val")) - as z(z); - $$ - }; - create function ltree::nlevel(v: ltree::ltree) -> std::int32 { - using sql function 'edgedb.nlevel'; - }; - }; - ''') - try: - async with self._run_and_rollback(): - await self._extension_test_01() - finally: - await self.con.execute(''' - drop extension package ltree VERSION '1.0' - ''') - - async def _extension_test_02a(self): - await self.con.execute(''' - create extension varchar - ''') - - await self.con.execute(''' - create scalar type vc5 extending ext::varchar::varchar<5>; - create type X { - create property foo: vc5; - }; - ''') - - await self.assert_query_result( - ''' - describe scalar type vc5; - ''', - [ - 'create scalar type default::vc5 ' - 'extending ext::varchar::varchar<5>;' - ], - ) - await self.assert_query_result( - ''' - describe scalar type vc5 as sdl; - ''', - ['scalar type default::vc5 extending ext::varchar::varchar<5>;'], - ) - - await self.assert_query_result( - ''' - select schema::ScalarType { arg_values } - filter .name = 'default::vc5' - ''', - [{'arg_values': ['5']}], - ) - - await self.con.execute(''' - insert X { foo := "0123456789" } - ''') - - await self.assert_query_result( - ''' - select X.foo - ''', - ['01234'], - json_only=True, - ) - - async with self.assertRaisesRegexTx( - edgedb.SchemaError, - "parameterized scalar types may not have constraints", - ): - await self.con.execute(''' - alter scalar type vc5 create constraint expression on (true); - ''') - - async with self.assertRaisesRegexTx( - edgedb.SchemaDefinitionError, - "invalid scalar type argument", - ): - await self.con.execute(''' - create scalar type fail extending ext::varchar::varchar; - ''') - - async with self.assertRaisesRegexTx( - edgedb.SchemaDefinitionError, - "does not accept parameters", - ): - await self.con.execute(''' - create scalar type yyy extending str<1, 2>; - ''') - - async with self.assertRaisesRegexTx( - edgedb.SchemaDefinitionError, - "incorrect number of arguments", - ): - await self.con.execute(''' - create scalar type yyy extending ext::varchar::varchar<1, 2>; - ''') - - # If no params are specified, it just makes a normal scalar type - await self.con.execute(''' - create scalar type vc extending ext::varchar::varchar { - create constraint expression on (false); - }; - ''') - async with self.assertRaisesRegexTx( - edgedb.ConstraintViolationError, - "invalid", - ): - await self.con.execute(''' - select 'a'; - ''') - - async def _extension_test_02b(self): - await self.con.execute(r""" - START MIGRATION TO { - using extension varchar version "1.0"; - module default { - scalar type vc5 extending ext::varchar::varchar<5>; - type X { - foo: vc5; - }; - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - await self.con.execute(''' - insert X { foo := "0123456789" } - ''') - - await self.assert_query_result( - ''' - select X.foo - ''', - ['01234'], - json_only=True, - ) - - # Try dropping everything that uses it but not the extension - async with self._run_and_rollback(): - await self.con.execute(r""" - START MIGRATION TO { - using extension varchar version "1.0"; - module default { - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - # Try dropping everything including the extension - await self.con.execute(r""" - START MIGRATION TO { - module default { - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - async def test_edgeql_ddl_extensions_02(self): - # Make an extension that wraps some of varchar - await self.con.execute(''' - create extension package varchar VERSION '1.0' { - set ext_module := "ext::varchar"; - set sql_extensions := []; - create module ext::varchar; - create scalar type ext::varchar::varchar { - create annotation std::description := 'why are we doing this'; - set id := '26dc1396-0196-11ee-a005-ad0eaed0df03'; - set sql_type := "varchar"; - set sql_type_scheme := "varchar({__arg_0__})"; - set num_params := 1; - }; - - create cast from ext::varchar::varchar to std::str { - SET volatility := 'Immutable'; - USING SQL CAST; - }; - create cast from std::str to ext::varchar::varchar { - SET volatility := 'Immutable'; - USING SQL CAST; - }; - # This is meaningless but I need to test having an array in a cast. - create cast from ext::varchar::varchar to array { - SET volatility := 'Immutable'; - USING SQL $$ - select array[0.0] - $$ - }; - - create abstract index ext::varchar::with_param( - named only lists: int64 - ) { - set code := ' ((__col__) NULLS FIRST)'; - }; - - create type ext::varchar::ParentTest { - create property foo -> str; - }; - create type ext::varchar::ChildTest - extending ext::varchar::ParentTest; - create type ext::varchar::GrandChildTest - extending ext::varchar::ChildTest; - }; - ''') - try: - async with self._run_and_rollback(): - await self._extension_test_02a() - async with self._run_and_rollback(): - await self._extension_test_02b() - finally: - await self.con.execute(''' - drop extension package varchar VERSION '1.0' - ''') - - async def test_edgeql_ddl_extensions_03(self): - await self.con.execute(''' - create extension package ltree_broken VERSION '1.0' { - set ext_module := "ltree"; - set sql_extensions := ["ltree >=1000.0"]; - create module ltree; - }; - ''') - try: - async with self.assertRaisesRegexTx( - edgedb.UnsupportedBackendFeatureError, - r"could not find extension satisfying ltree >=1000.0: " - r"only found versions 1\."): - await self.con.execute(r""" - CREATE EXTENSION ltree_broken; - """) - finally: - await self.con.execute(''' - drop extension package ltree_broken VERSION '1.0' - ''') - - async def test_edgeql_ddl_extensions_04(self): - await self.con.execute(''' - create extension package ltree_broken VERSION '1.0' { - set ext_module := "ltree"; - set sql_extensions := ["loltree >=1.0"]; - create module ltree; - }; - ''') - try: - async with self.assertRaisesRegexTx( - edgedb.UnsupportedBackendFeatureError, - r"could not find extension satisfying loltree >=1.0: " - r"extension not found"): - await self.con.execute(r""" - CREATE EXTENSION ltree_broken; - """) - finally: - await self.con.execute(''' - drop extension package ltree_broken VERSION '1.0' - ''') - - async def _extension_test_05(self, in_tx): - await self.con.execute(''' - create extension _conf - ''') - - # Check that the ids are stable - await self.assert_query_result( - ''' - select schema::ObjectType { - id, - properties: { name, id } filter .name = 'value' - } filter .name = 'ext::_conf::Obj' - ''', - [ - { - "id": "dc7c6ed1-759f-5a70-9bc3-2252b2d3980a", - "properties": [ - { - "name": "value", - "id": "0dff1c2f-f51b-59fd-bae9-9d66cb963896", - }, - ], - }, - ], - ) - - Q = ''' - select cfg::%s { - conf := assert_single(.extensions[is ext::_conf::Config] { - config_name, - opt_value, - obj: { name, value, fixed }, - objs: { name, value, opt_value, - [is ext::_conf::SubObj].extra, - tname := .__type__.name } - order by .name, - }) - }; - ''' - - async def _check(_cfg_obj='Config', **kwargs): - q = Q % _cfg_obj - await self.assert_query_result( - q, - [{'conf': kwargs}], - ) - - await _check( - config_name='', - objs=[], - ) - - await self.con.execute(''' - configure current database set ext::_conf::Config::config_name := - "test"; - ''') - - await _check( - config_name='test', - opt_value=None, - objs=[], - ) - - await self.con.execute(''' - configure current database set ext::_conf::Config::opt_value := - "opt!"; - ''') - - await self.con.execute(''' - configure current database set ext::_conf::Config::secret := - "foobaz"; - ''') - - await _check( - config_name='test', - opt_value='opt!', - objs=[], - ) - - if not in_tx: - with self.assertRaisesRegex( - edgedb.ConfigurationError, "is not allowed"): - await self.con.execute(''' - configure instance set ext::_conf::Config::config_name := - "session!"; - ''') - - await self.con.execute(''' - configure session set ext::_conf::Config::config_name := - "session!"; - ''') - - await _check( - config_name='session!', - objs=[], - ) - - await self.con.execute(''' - configure session reset ext::_conf::Config::config_name; - ''') - - await _check( - config_name='test', - objs=[], - ) - - await self.con.execute(''' - configure current database insert ext::_conf::Obj { - name := '1', - value := 'foo', - }; - ''') - await self.con.execute(''' - configure current database insert ext::_conf::Obj { - name := '2', - value := 'bar', - opt_value := 'opt.', - }; - ''') - await self.con.execute(''' - configure current database insert ext::_conf::SubObj { - name := '3', - value := 'baz', - extra := 42, - }; - ''') - - async with self.assertRaisesRegexTx( - edgedb.ConfigurationError, "invalid setting value" - ): - await self.con.execute(''' - configure current database insert ext::_conf::SubObj { - name := '3!', - value := 'asdf_wrong', - extra := 42, - }; - ''') - - # This is fine, constraint on value is delegated - await self.con.execute(''' - configure current database insert ext::_conf::SecretObj { - name := '4', - value := 'foo', - secret := '123456', - }; - ''') - - # But this collides - async with self.assertRaisesRegexTx( - edgedb.ConstraintViolationError, "value violate" - ): - await self.con.execute(''' - configure current database insert ext::_conf::SecretObj { - name := '5', - value := 'foo', - }; - ''') - - await self.con.execute(''' - configure current database insert ext::_conf::SecretObj { - name := '5', - value := 'quux', - }; - ''') - async with self.assertRaisesRegexTx( - edgedb.QueryError, "protected" - ): - await self.con.execute(''' - configure current database insert ext::_conf::SingleObj { - name := 'single', - value := 'val', - fixed := 'variable??', - }; - ''') - - await self.con.execute(''' - configure current database insert ext::_conf::SingleObj { - name := 'single', - value := 'val', - }; - ''') - - async with self.assertRaisesRegexTx( - edgedb.ConstraintViolationError, "" - ): - await self.con.execute(''' - CONFIGURE CURRENT DATABASE INSERT ext::_conf::SingleObj { - name := 'fail', - value := '', - }; - ''') - - await self.con.execute(''' - configure current database set ext::_conf::Config::config_name := - "ready"; - ''') - - await _check( - config_name='ready', - objs=[ - dict(name='1', value='foo', tname='ext::_conf::Obj', - opt_value=None), - dict(name='2', value='bar', tname='ext::_conf::Obj', - opt_value='opt.'), - dict(name='3', value='baz', extra=42, - tname='ext::_conf::SubObj', opt_value=None), - dict(name='4', value='foo', - tname='ext::_conf::SecretObj', opt_value=None), - dict(name='5', value='quux', - tname='ext::_conf::SecretObj', opt_value=None), - ], - obj=dict(name='single', value='val', fixed='fixed!'), - ) - - await self.assert_query_result( - ''' - with c := cfg::Config.extensions[is ext::_conf::Config] - select ext::_conf::get_secret( - (select c.objs[is ext::_conf::SecretObj] filter .name = '4')) - ''', - ['123456'], - ) - await self.assert_query_result( - ''' - select ext::_conf::get_top_secret() - ''', - ['foobaz'], - ) - - await self.assert_query_result( - ''' - select ext::_conf::OK - ''', - [True], - ) - await self.con.execute(''' - configure current database set ext::_conf::Config::secret := - "123456"; - ''') - await self.assert_query_result( - ''' - select ext::_conf::OK - ''', - [False], - ) - - # Make sure secrets are redacted from get_config_json - cfg_json = await self.con.query_single(''' - select to_str(cfg::get_config_json()); - ''') - self.assertNotIn('123456', cfg_json, 'secrets not redacted') - - # test not being able to access secrets - async with self.assertRaisesRegexTx( - edgedb.QueryError, "because it is secret" - ): - await self.con.execute(''' - select cfg::Config { - conf := assert_single(.extensions[is ext::_conf::Config] { - secret - }) - }; - ''') - async with self.assertRaisesRegexTx( - edgedb.QueryError, "because it is secret" - ): - await self.con.execute(''' - select cfg::Config { - conf := assert_single( - .extensions[is ext::_conf::Config] { - objs: { [is ext::_conf::SecretObj].secret } - }) - }; - ''') - async with self.assertRaisesRegexTx( - edgedb.QueryError, "because it is secret" - ): - await self.con.execute(''' - select ext::_conf::Config.secret - ''') - async with self.assertRaisesRegexTx( - edgedb.QueryError, "because it is secret" - ): - await self.con.execute(''' - select ext::_conf::SecretObj.secret - ''') - async with self.assertRaisesRegexTx( - edgedb.QueryError, "because it is secret" - ): - await self.con.execute(''' - configure current database reset ext::_conf::SecretObj - filter .secret = '123456' - ''') - - if not in_tx: - # Load the in-memory config state via a HTTP debug endpoint - # Retry until we see 'ready' is visible - async for tr in self.try_until_succeeds(ignore=AssertionError): - async with tr: - with self.http_con() as http_con: - rdata, _headers, status = self.http_con_request( - http_con, - prefix="", - path="server-info", - ) - data = json.loads(rdata) - if 'databases' not in data: - # multi-tenant instance - use the first tenant - data = next(iter(data['tenants'].values())) - db_data = data['databases'][self.get_database_name()] - config = db_data['config'] - assert ( - config['ext::_conf::Config::config_name'] == 'ready' - ) - - self.assertEqual( - sorted( - config['ext::_conf::Config::objs'], - key=lambda x: x['name'], - ), - [ - {'_tname': 'ext::_conf::Obj', - 'name': '1', 'value': 'foo', 'opt_value': None}, - {'_tname': 'ext::_conf::Obj', - 'name': '2', 'value': 'bar', 'opt_value': 'opt.'}, - {'_tname': 'ext::_conf::SubObj', - 'name': '3', 'value': 'baz', 'extra': 42, - 'duration_config': 'PT10M', - 'opt_value': None}, - {'_tname': 'ext::_conf::SecretObj', - 'name': '4', 'value': 'foo', - 'opt_value': None, 'secret': {'redacted': True}}, - {'_tname': 'ext::_conf::SecretObj', - 'name': '5', 'value': 'quux', - 'opt_value': None, 'secret': None}, - ], - ) - self.assertEqual( - config['ext::_conf::Config::obj'], - {'_tname': 'ext::_conf::SingleObj', - 'name': 'single', 'value': 'val', 'fixed': 'fixed!'}, - ) - - val = await self.con.query_single(''' - describe current database config - ''') - test_expected = textwrap.dedent('''\ - CONFIGURE CURRENT DATABASE SET ext::_conf::Config::config_name := \ -'ready'; - CONFIGURE CURRENT DATABASE INSERT ext::_conf::SingleObj { - name := 'single', - value := 'val', - }; - CONFIGURE CURRENT DATABASE INSERT ext::_conf::Obj { - name := '1', - value := 'foo', - }; - CONFIGURE CURRENT DATABASE INSERT ext::_conf::Obj { - name := '2', - opt_value := 'opt.', - value := 'bar', - }; - CONFIGURE CURRENT DATABASE INSERT ext::_conf::SecretObj { - name := '4', - secret := {}, # REDACTED - value := 'foo', - }; - CONFIGURE CURRENT DATABASE INSERT ext::_conf::SecretObj { - name := '5', - secret := {}, # REDACTED - value := 'quux', - }; - CONFIGURE CURRENT DATABASE INSERT ext::_conf::SubObj { - duration_config := 'PT10M', - extra := 42, - name := '3', - value := 'baz', - }; - CONFIGURE CURRENT DATABASE SET ext::_conf::Config::opt_value := 'opt!'; - CONFIGURE CURRENT DATABASE SET ext::_conf::Config::secret := \ -{}; # REDACTED - ''') - self.assertEqual(val, test_expected) - - await self.con.execute(''' - configure current database reset ext::_conf::Obj - filter .value like 'ba%' - ''') - await self.con.execute(''' - configure current database reset ext::_conf::SecretObj - ''') - - await _check( - config_name='ready', - objs=[ - dict(name='1', value='foo'), - ], - ) - - await self.con.execute(''' - configure current database reset ext::_conf::Obj - ''') - await self.con.execute(''' - configure current database reset ext::_conf::Config::opt_value; - ''') - - await _check( - config_name='ready', - opt_value=None, - objs=[], - obj=dict(name='single', value='val'), - ) - - await self.con.execute(''' - configure current database reset ext::_conf::SingleObj - ''') - await _check( - config_name='ready', - opt_value=None, - objs=[], - obj=None, - ) - - await self.con.execute(''' - configure current database reset ext::_conf::Config::secret; - ''') - await self.con.execute(''' - configure current database reset ext::_conf::Config::config_name; - ''') - - await _check( - config_name='', - objs=[], - ) - - if not in_tx: - con2 = await self.connect(database=self.con.dbname) - try: - await con2.query('select 1') - await self.con.execute(''' - CONFIGURE CURRENT DATABASE INSERT ext::_conf::Obj { - name := 'fail', - value := '', - }; - ''') - - # This needs to fail - with self.assertRaisesRegex( - edgedb.ConstraintViolationError, "" - ): - await self.con.execute(''' - CONFIGURE CURRENT DATABASE INSERT ext::_conf::Obj { - name := 'fail', - value := '', - }; - insert Test; - ''') - - # The code path by which the above fails is subtle (it - # gets triggered by config processing code in the - # server). Make sure that the error properly aborts - # the whole script. - await self.assert_query_result( - 'select count(Test)', - [0], - ) - - finally: - await con2.aclose() - - async def test_edgeql_ddl_extensions_05(self): - # Test config extension - await self.con.execute(''' - create type Test; - ''') - - try: - async with self._run_and_rollback(): - await self._extension_test_05(in_tx=True) - try: - await self._extension_test_05(in_tx=False) - finally: - await self.con.execute(''' - drop extension _conf - ''') - finally: - await self.con.execute(''' - drop type Test; - ''') - - async def _extension_test_06b(self): - await self.con.execute(r""" - START MIGRATION TO { - using extension bar version "2.0"; - module default { - function lol() -> str using (ext::bar::fubar()) - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - await self.assert_query_result( - 'select lol()', - ['foobar'], - ) - - # Try dropping everything that uses it but not the extension - async with self._run_and_rollback(): - await self.con.execute(r""" - START MIGRATION TO { - using extension bar version "2.0"; - module default { - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - # Try dropping it but adding bar - async with self._run_and_rollback(): - await self.con.execute(r""" - START MIGRATION TO { - using extension bar version "2.0"; - module default { - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - # Try dropping everything including the extension - await self.con.execute(r""" - START MIGRATION TO { - module default { - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - # Try it explicitly specifying an old version. Note - # that we don't *yet* support upgrading between extension - # versions; you need to drop it and recreate everything, which - # obviously is not great. - - await self.con.execute(r""" - START MIGRATION TO { - using extension bar version '1.0'; - module default { - function lol() -> str using (ext::bar::fubar()) - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - await self.assert_query_result( - 'select lol()', - ['foo?bar'], - ) - - # Try dropping everything including the extension - await self.con.execute(r""" - START MIGRATION TO { - module default { - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - with self.assertRaisesRegex( - edgedb.SchemaError, - "cannot install extension 'foo' version 2.0: " - "version 1.0 is already installed" - ): - await self.con.execute(r""" - START MIGRATION TO { - using extension bar version '1.0'; - using extension foo version '2.0'; - module default { - } - }; - POPULATE MIGRATION; - COMMIT MIGRATION; - """) - - async def test_edgeql_ddl_extensions_06(self): - # Make an extension with dependencies - await self.con.execute(''' - create extension package foo VERSION '1.0' { - set ext_module := "ext::foo"; - create module ext::foo; - create function ext::foo::test() -> str using ("foo?"); - }; - create extension package foo VERSION '2.0' { - set ext_module := "ext::foo"; - create module ext::foo; - create function ext::foo::test() -> str using ("foo"); - }; - create extension package bar VERSION '1.0' { - set ext_module := "ext::bar"; - set dependencies := ["foo==1.0"]; - create module ext::bar; - create function ext::bar::fubar() -> str using ( - ext::foo::test() ++ "bar" - ); - }; - create extension package bar VERSION '2.0' { - set ext_module := "ext::bar"; - set dependencies := ["foo==2.0"]; - create module ext::bar; - create function ext::bar::fubar() -> str using ( - ext::foo::test() ++ "bar" - ); - }; - ''') - try: - async with self._run_and_rollback(): - await self._extension_test_06b() - finally: - await self.con.execute(''' - drop extension package bar VERSION '1.0'; - drop extension package foo VERSION '1.0'; - drop extension package bar VERSION '2.0'; - drop extension package foo VERSION '2.0'; - ''') - async def test_edgeql_ddl_reindex(self): await self.con.execute(''' create type Tgt; diff --git a/tests/test_edgeql_extensions.py b/tests/test_edgeql_extensions.py new file mode 100644 index 00000000000..f5e493c1bba --- /dev/null +++ b/tests/test_edgeql_extensions.py @@ -0,0 +1,995 @@ +# +# This source file is part of the EdgeDB open source project. +# +# Copyright 2016-present MagicStack Inc. and the EdgeDB authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import json +import textwrap + +import edgedb + +from edb.testbase import server as tb + + +class TestDDLExtensions(tb.DDLTestCase): + TRANSACTION_ISOLATION = False + PARALLELISM_GRANULARITY = 'suite' + + async def _extension_test_01(self): + await self.con.execute(''' + create extension ltree + ''') + + await self.assert_query_result( + ''' + select ltree::nlevel( + 'foo.bar'); + ''', + [2], + ) + await self.assert_query_result( + ''' + select ( + 'foo.bar'); + ''', + ['foo.bar'], + ) + await self.assert_query_result( + ''' + select 'foo.bar'; + ''', + [['foo', 'bar']], + json_only=True, + ) + + await self.con.execute(''' + create type Foo { create property x -> ltree::ltree }; + insert Foo { x := 'foo.bar.baz' }; + ''') + + await self.assert_query_result( + ''' + select Foo.x; + ''', + [['foo', 'bar', 'baz']], + json_only=True, + ) + + await self.con.execute(''' + drop type Foo; + drop extension ltree; + ''') + + async def test_edgeql_extensions_01(self): + # Make an extension that wraps a tiny bit of the ltree package. + await self.con.execute(''' + create extension package ltree VERSION '1.0' { + set ext_module := "ltree"; + set sql_extensions := ["ltree >=1.0,<10.0"]; + create module ltree; + create scalar type ltree::ltree { + set sql_type := "ltree"; + }; + create cast from ltree::ltree to std::str { + SET volatility := 'Immutable'; + USING SQL CAST; + }; + create cast from std::str to ltree::ltree { + SET volatility := 'Immutable'; + USING SQL CAST; + }; + + # Use a non-trivial json representation just to show that we can. + create cast from ltree::ltree to std::json { + SET volatility := 'Immutable'; + USING SQL $$ + select to_jsonb(string_to_array("val"::text, '.')); + $$ + }; + create cast from std::json to ltree::ltree { + SET volatility := 'Immutable'; + USING SQL $$ + select string_agg(edgedb.raise_on_null( + edgedbstd."std|cast@std|json@std|str_f"(z.z), + 'invalid_parameter_value', 'invalid null value in cast'), + '.')::ltree + from unnest( + edgedbstd."std|cast@std|json@array_f"("val")) + as z(z); + $$ + }; + create function ltree::nlevel(v: ltree::ltree) -> std::int32 { + using sql function 'edgedb.nlevel'; + }; + }; + ''') + try: + async with self._run_and_rollback(): + await self._extension_test_01() + finally: + await self.con.execute(''' + drop extension package ltree VERSION '1.0' + ''') + + async def _extension_test_02a(self): + await self.con.execute(''' + create extension varchar + ''') + + await self.con.execute(''' + create scalar type vc5 extending ext::varchar::varchar<5>; + create type X { + create property foo: vc5; + }; + ''') + + await self.assert_query_result( + ''' + describe scalar type vc5; + ''', + [ + 'create scalar type default::vc5 ' + 'extending ext::varchar::varchar<5>;' + ], + ) + await self.assert_query_result( + ''' + describe scalar type vc5 as sdl; + ''', + ['scalar type default::vc5 extending ext::varchar::varchar<5>;'], + ) + + await self.assert_query_result( + ''' + select schema::ScalarType { arg_values } + filter .name = 'default::vc5' + ''', + [{'arg_values': ['5']}], + ) + + await self.con.execute(''' + insert X { foo := "0123456789" } + ''') + + await self.assert_query_result( + ''' + select X.foo + ''', + ['01234'], + json_only=True, + ) + + async with self.assertRaisesRegexTx( + edgedb.SchemaError, + "parameterized scalar types may not have constraints", + ): + await self.con.execute(''' + alter scalar type vc5 create constraint expression on (true); + ''') + + async with self.assertRaisesRegexTx( + edgedb.SchemaDefinitionError, + "invalid scalar type argument", + ): + await self.con.execute(''' + create scalar type fail extending ext::varchar::varchar; + ''') + + async with self.assertRaisesRegexTx( + edgedb.SchemaDefinitionError, + "does not accept parameters", + ): + await self.con.execute(''' + create scalar type yyy extending str<1, 2>; + ''') + + async with self.assertRaisesRegexTx( + edgedb.SchemaDefinitionError, + "incorrect number of arguments", + ): + await self.con.execute(''' + create scalar type yyy extending ext::varchar::varchar<1, 2>; + ''') + + # If no params are specified, it just makes a normal scalar type + await self.con.execute(''' + create scalar type vc extending ext::varchar::varchar { + create constraint expression on (false); + }; + ''') + async with self.assertRaisesRegexTx( + edgedb.ConstraintViolationError, + "invalid", + ): + await self.con.execute(''' + select 'a'; + ''') + + async def _extension_test_02b(self): + await self.con.execute(r""" + START MIGRATION TO { + using extension varchar version "1.0"; + module default { + scalar type vc5 extending ext::varchar::varchar<5>; + type X { + foo: vc5; + }; + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + await self.con.execute(''' + insert X { foo := "0123456789" } + ''') + + await self.assert_query_result( + ''' + select X.foo + ''', + ['01234'], + json_only=True, + ) + + # Try dropping everything that uses it but not the extension + async with self._run_and_rollback(): + await self.con.execute(r""" + START MIGRATION TO { + using extension varchar version "1.0"; + module default { + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + # Try dropping everything including the extension + await self.con.execute(r""" + START MIGRATION TO { + module default { + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + async def test_edgeql_extensions_02(self): + # Make an extension that wraps some of varchar + await self.con.execute(''' + create extension package varchar VERSION '1.0' { + set ext_module := "ext::varchar"; + set sql_extensions := []; + create module ext::varchar; + create scalar type ext::varchar::varchar { + create annotation std::description := 'why are we doing this'; + set id := '26dc1396-0196-11ee-a005-ad0eaed0df03'; + set sql_type := "varchar"; + set sql_type_scheme := "varchar({__arg_0__})"; + set num_params := 1; + }; + + create cast from ext::varchar::varchar to std::str { + SET volatility := 'Immutable'; + USING SQL CAST; + }; + create cast from std::str to ext::varchar::varchar { + SET volatility := 'Immutable'; + USING SQL CAST; + }; + # This is meaningless but I need to test having an array in a cast. + create cast from ext::varchar::varchar to array { + SET volatility := 'Immutable'; + USING SQL $$ + select array[0.0] + $$ + }; + + create abstract index ext::varchar::with_param( + named only lists: int64 + ) { + set code := ' ((__col__) NULLS FIRST)'; + }; + + create type ext::varchar::ParentTest { + create property foo -> str; + }; + create type ext::varchar::ChildTest + extending ext::varchar::ParentTest; + create type ext::varchar::GrandChildTest + extending ext::varchar::ChildTest; + }; + ''') + try: + async with self._run_and_rollback(): + await self._extension_test_02a() + async with self._run_and_rollback(): + await self._extension_test_02b() + finally: + await self.con.execute(''' + drop extension package varchar VERSION '1.0' + ''') + + async def test_edgeql_extensions_03(self): + await self.con.execute(''' + create extension package ltree_broken VERSION '1.0' { + set ext_module := "ltree"; + set sql_extensions := ["ltree >=1000.0"]; + create module ltree; + }; + ''') + try: + async with self.assertRaisesRegexTx( + edgedb.UnsupportedBackendFeatureError, + r"could not find extension satisfying ltree >=1000.0: " + r"only found versions 1\."): + await self.con.execute(r""" + CREATE EXTENSION ltree_broken; + """) + finally: + await self.con.execute(''' + drop extension package ltree_broken VERSION '1.0' + ''') + + async def test_edgeql_extensions_04(self): + await self.con.execute(''' + create extension package ltree_broken VERSION '1.0' { + set ext_module := "ltree"; + set sql_extensions := ["loltree >=1.0"]; + create module ltree; + }; + ''') + try: + async with self.assertRaisesRegexTx( + edgedb.UnsupportedBackendFeatureError, + r"could not find extension satisfying loltree >=1.0: " + r"extension not found"): + await self.con.execute(r""" + CREATE EXTENSION ltree_broken; + """) + finally: + await self.con.execute(''' + drop extension package ltree_broken VERSION '1.0' + ''') + + async def _extension_test_05(self, in_tx): + await self.con.execute(''' + create extension _conf + ''') + + # Check that the ids are stable + await self.assert_query_result( + ''' + select schema::ObjectType { + id, + properties: { name, id } filter .name = 'value' + } filter .name = 'ext::_conf::Obj' + ''', + [ + { + "id": "dc7c6ed1-759f-5a70-9bc3-2252b2d3980a", + "properties": [ + { + "name": "value", + "id": "0dff1c2f-f51b-59fd-bae9-9d66cb963896", + }, + ], + }, + ], + ) + + Q = ''' + select cfg::%s { + conf := assert_single(.extensions[is ext::_conf::Config] { + config_name, + opt_value, + obj: { name, value, fixed }, + objs: { name, value, opt_value, + [is ext::_conf::SubObj].extra, + tname := .__type__.name } + order by .name, + }) + }; + ''' + + async def _check(_cfg_obj='Config', **kwargs): + q = Q % _cfg_obj + await self.assert_query_result( + q, + [{'conf': kwargs}], + ) + + await _check( + config_name='', + objs=[], + ) + + await self.con.execute(''' + configure current database set ext::_conf::Config::config_name := + "test"; + ''') + + await _check( + config_name='test', + opt_value=None, + objs=[], + ) + + await self.con.execute(''' + configure current database set ext::_conf::Config::opt_value := + "opt!"; + ''') + + await self.con.execute(''' + configure current database set ext::_conf::Config::secret := + "foobaz"; + ''') + + await _check( + config_name='test', + opt_value='opt!', + objs=[], + ) + + if not in_tx: + with self.assertRaisesRegex( + edgedb.ConfigurationError, "is not allowed"): + await self.con.execute(''' + configure instance set ext::_conf::Config::config_name := + "session!"; + ''') + + await self.con.execute(''' + configure session set ext::_conf::Config::config_name := + "session!"; + ''') + + await _check( + config_name='session!', + objs=[], + ) + + await self.con.execute(''' + configure session reset ext::_conf::Config::config_name; + ''') + + await _check( + config_name='test', + objs=[], + ) + + await self.con.execute(''' + configure current database insert ext::_conf::Obj { + name := '1', + value := 'foo', + }; + ''') + await self.con.execute(''' + configure current database insert ext::_conf::Obj { + name := '2', + value := 'bar', + opt_value := 'opt.', + }; + ''') + await self.con.execute(''' + configure current database insert ext::_conf::SubObj { + name := '3', + value := 'baz', + extra := 42, + }; + ''') + + async with self.assertRaisesRegexTx( + edgedb.ConfigurationError, "invalid setting value" + ): + await self.con.execute(''' + configure current database insert ext::_conf::SubObj { + name := '3!', + value := 'asdf_wrong', + extra := 42, + }; + ''') + + # This is fine, constraint on value is delegated + await self.con.execute(''' + configure current database insert ext::_conf::SecretObj { + name := '4', + value := 'foo', + secret := '123456', + }; + ''') + + # But this collides + async with self.assertRaisesRegexTx( + edgedb.ConstraintViolationError, "value violate" + ): + await self.con.execute(''' + configure current database insert ext::_conf::SecretObj { + name := '5', + value := 'foo', + }; + ''') + + await self.con.execute(''' + configure current database insert ext::_conf::SecretObj { + name := '5', + value := 'quux', + }; + ''') + async with self.assertRaisesRegexTx( + edgedb.QueryError, "protected" + ): + await self.con.execute(''' + configure current database insert ext::_conf::SingleObj { + name := 'single', + value := 'val', + fixed := 'variable??', + }; + ''') + + await self.con.execute(''' + configure current database insert ext::_conf::SingleObj { + name := 'single', + value := 'val', + }; + ''') + + async with self.assertRaisesRegexTx( + edgedb.ConstraintViolationError, "" + ): + await self.con.execute(''' + CONFIGURE CURRENT DATABASE INSERT ext::_conf::SingleObj { + name := 'fail', + value := '', + }; + ''') + + await self.con.execute(''' + configure current database set ext::_conf::Config::config_name := + "ready"; + ''') + + await _check( + config_name='ready', + objs=[ + dict(name='1', value='foo', tname='ext::_conf::Obj', + opt_value=None), + dict(name='2', value='bar', tname='ext::_conf::Obj', + opt_value='opt.'), + dict(name='3', value='baz', extra=42, + tname='ext::_conf::SubObj', opt_value=None), + dict(name='4', value='foo', + tname='ext::_conf::SecretObj', opt_value=None), + dict(name='5', value='quux', + tname='ext::_conf::SecretObj', opt_value=None), + ], + obj=dict(name='single', value='val', fixed='fixed!'), + ) + + await self.assert_query_result( + ''' + with c := cfg::Config.extensions[is ext::_conf::Config] + select ext::_conf::get_secret( + (select c.objs[is ext::_conf::SecretObj] filter .name = '4')) + ''', + ['123456'], + ) + await self.assert_query_result( + ''' + select ext::_conf::get_top_secret() + ''', + ['foobaz'], + ) + + await self.assert_query_result( + ''' + select ext::_conf::OK + ''', + [True], + ) + await self.con.execute(''' + configure current database set ext::_conf::Config::secret := + "123456"; + ''') + await self.assert_query_result( + ''' + select ext::_conf::OK + ''', + [False], + ) + + # Make sure secrets are redacted from get_config_json + cfg_json = await self.con.query_single(''' + select to_str(cfg::get_config_json()); + ''') + self.assertNotIn('123456', cfg_json, 'secrets not redacted') + + # test not being able to access secrets + async with self.assertRaisesRegexTx( + edgedb.QueryError, "because it is secret" + ): + await self.con.execute(''' + select cfg::Config { + conf := assert_single(.extensions[is ext::_conf::Config] { + secret + }) + }; + ''') + async with self.assertRaisesRegexTx( + edgedb.QueryError, "because it is secret" + ): + await self.con.execute(''' + select cfg::Config { + conf := assert_single( + .extensions[is ext::_conf::Config] { + objs: { [is ext::_conf::SecretObj].secret } + }) + }; + ''') + async with self.assertRaisesRegexTx( + edgedb.QueryError, "because it is secret" + ): + await self.con.execute(''' + select ext::_conf::Config.secret + ''') + async with self.assertRaisesRegexTx( + edgedb.QueryError, "because it is secret" + ): + await self.con.execute(''' + select ext::_conf::SecretObj.secret + ''') + async with self.assertRaisesRegexTx( + edgedb.QueryError, "because it is secret" + ): + await self.con.execute(''' + configure current database reset ext::_conf::SecretObj + filter .secret = '123456' + ''') + + if not in_tx: + # Load the in-memory config state via a HTTP debug endpoint + # Retry until we see 'ready' is visible + async for tr in self.try_until_succeeds(ignore=AssertionError): + async with tr: + with self.http_con() as http_con: + rdata, _headers, status = self.http_con_request( + http_con, + prefix="", + path="server-info", + ) + data = json.loads(rdata) + if 'databases' not in data: + # multi-tenant instance - use the first tenant + data = next(iter(data['tenants'].values())) + db_data = data['databases'][self.get_database_name()] + config = db_data['config'] + assert ( + config['ext::_conf::Config::config_name'] == 'ready' + ) + + self.assertEqual( + sorted( + config['ext::_conf::Config::objs'], + key=lambda x: x['name'], + ), + [ + {'_tname': 'ext::_conf::Obj', + 'name': '1', 'value': 'foo', 'opt_value': None}, + {'_tname': 'ext::_conf::Obj', + 'name': '2', 'value': 'bar', 'opt_value': 'opt.'}, + {'_tname': 'ext::_conf::SubObj', + 'name': '3', 'value': 'baz', 'extra': 42, + 'duration_config': 'PT10M', + 'opt_value': None}, + {'_tname': 'ext::_conf::SecretObj', + 'name': '4', 'value': 'foo', + 'opt_value': None, 'secret': {'redacted': True}}, + {'_tname': 'ext::_conf::SecretObj', + 'name': '5', 'value': 'quux', + 'opt_value': None, 'secret': None}, + ], + ) + self.assertEqual( + config['ext::_conf::Config::obj'], + {'_tname': 'ext::_conf::SingleObj', + 'name': 'single', 'value': 'val', 'fixed': 'fixed!'}, + ) + + val = await self.con.query_single(''' + describe current database config + ''') + test_expected = textwrap.dedent('''\ + CONFIGURE CURRENT DATABASE SET ext::_conf::Config::config_name := \ +'ready'; + CONFIGURE CURRENT DATABASE INSERT ext::_conf::SingleObj { + name := 'single', + value := 'val', + }; + CONFIGURE CURRENT DATABASE INSERT ext::_conf::Obj { + name := '1', + value := 'foo', + }; + CONFIGURE CURRENT DATABASE INSERT ext::_conf::Obj { + name := '2', + opt_value := 'opt.', + value := 'bar', + }; + CONFIGURE CURRENT DATABASE INSERT ext::_conf::SecretObj { + name := '4', + secret := {}, # REDACTED + value := 'foo', + }; + CONFIGURE CURRENT DATABASE INSERT ext::_conf::SecretObj { + name := '5', + secret := {}, # REDACTED + value := 'quux', + }; + CONFIGURE CURRENT DATABASE INSERT ext::_conf::SubObj { + duration_config := 'PT10M', + extra := 42, + name := '3', + value := 'baz', + }; + CONFIGURE CURRENT DATABASE SET ext::_conf::Config::opt_value := 'opt!'; + CONFIGURE CURRENT DATABASE SET ext::_conf::Config::secret := \ +{}; # REDACTED + ''') + self.assertEqual(val, test_expected) + + await self.con.execute(''' + configure current database reset ext::_conf::Obj + filter .value like 'ba%' + ''') + await self.con.execute(''' + configure current database reset ext::_conf::SecretObj + ''') + + await _check( + config_name='ready', + objs=[ + dict(name='1', value='foo'), + ], + ) + + await self.con.execute(''' + configure current database reset ext::_conf::Obj + ''') + await self.con.execute(''' + configure current database reset ext::_conf::Config::opt_value; + ''') + + await _check( + config_name='ready', + opt_value=None, + objs=[], + obj=dict(name='single', value='val'), + ) + + await self.con.execute(''' + configure current database reset ext::_conf::SingleObj + ''') + await _check( + config_name='ready', + opt_value=None, + objs=[], + obj=None, + ) + + await self.con.execute(''' + configure current database reset ext::_conf::Config::secret; + ''') + await self.con.execute(''' + configure current database reset ext::_conf::Config::config_name; + ''') + + await _check( + config_name='', + objs=[], + ) + + if not in_tx: + con2 = await self.connect(database=self.con.dbname) + try: + await con2.query('select 1') + await self.con.execute(''' + CONFIGURE CURRENT DATABASE INSERT ext::_conf::Obj { + name := 'fail', + value := '', + }; + ''') + + # This needs to fail + with self.assertRaisesRegex( + edgedb.ConstraintViolationError, "" + ): + await self.con.execute(''' + CONFIGURE CURRENT DATABASE INSERT ext::_conf::Obj { + name := 'fail', + value := '', + }; + insert Test; + ''') + + # The code path by which the above fails is subtle (it + # gets triggered by config processing code in the + # server). Make sure that the error properly aborts + # the whole script. + await self.assert_query_result( + 'select count(Test)', + [0], + ) + + finally: + await con2.aclose() + + async def test_edgeql_extensions_05(self): + # Test config extension + await self.con.execute(''' + create type Test; + ''') + + try: + async with self._run_and_rollback(): + await self._extension_test_05(in_tx=True) + try: + await self._extension_test_05(in_tx=False) + finally: + await self.con.execute(''' + drop extension _conf + ''') + finally: + await self.con.execute(''' + drop type Test; + ''') + + async def _extension_test_06b(self): + await self.con.execute(r""" + START MIGRATION TO { + using extension bar version "2.0"; + module default { + function lol() -> str using (ext::bar::fubar()) + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + await self.assert_query_result( + 'select lol()', + ['foobar'], + ) + + # Try dropping everything that uses it but not the extension + async with self._run_and_rollback(): + await self.con.execute(r""" + START MIGRATION TO { + using extension bar version "2.0"; + module default { + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + # Try dropping it but adding bar + async with self._run_and_rollback(): + await self.con.execute(r""" + START MIGRATION TO { + using extension bar version "2.0"; + module default { + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + # Try dropping everything including the extension + await self.con.execute(r""" + START MIGRATION TO { + module default { + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + # Try it explicitly specifying an old version. Note + # that we don't *yet* support upgrading between extension + # versions; you need to drop it and recreate everything, which + # obviously is not great. + + await self.con.execute(r""" + START MIGRATION TO { + using extension bar version '1.0'; + module default { + function lol() -> str using (ext::bar::fubar()) + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + await self.assert_query_result( + 'select lol()', + ['foo?bar'], + ) + + # Try dropping everything including the extension + await self.con.execute(r""" + START MIGRATION TO { + module default { + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + with self.assertRaisesRegex( + edgedb.SchemaError, + "cannot install extension 'foo' version 2.0: " + "version 1.0 is already installed" + ): + await self.con.execute(r""" + START MIGRATION TO { + using extension bar version '1.0'; + using extension foo version '2.0'; + module default { + } + }; + POPULATE MIGRATION; + COMMIT MIGRATION; + """) + + async def test_edgeql_extensions_06(self): + # Make an extension with dependencies + await self.con.execute(''' + create extension package foo VERSION '1.0' { + set ext_module := "ext::foo"; + create module ext::foo; + create function ext::foo::test() -> str using ("foo?"); + }; + create extension package foo VERSION '2.0' { + set ext_module := "ext::foo"; + create module ext::foo; + create function ext::foo::test() -> str using ("foo"); + }; + create extension package bar VERSION '1.0' { + set ext_module := "ext::bar"; + set dependencies := ["foo==1.0"]; + create module ext::bar; + create function ext::bar::fubar() -> str using ( + ext::foo::test() ++ "bar" + ); + }; + create extension package bar VERSION '2.0' { + set ext_module := "ext::bar"; + set dependencies := ["foo==2.0"]; + create module ext::bar; + create function ext::bar::fubar() -> str using ( + ext::foo::test() ++ "bar" + ); + }; + ''') + try: + async with self._run_and_rollback(): + await self._extension_test_06b() + finally: + await self.con.execute(''' + drop extension package bar VERSION '1.0'; + drop extension package foo VERSION '1.0'; + drop extension package bar VERSION '2.0'; + drop extension package foo VERSION '2.0'; + ''') From 84d004990c2249cfe4f86e853106fef217e613be Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Thu, 29 Feb 2024 23:21:52 -0800 Subject: [PATCH 2/7] wtf... try doing a retry just to see if it helps --- edb/common/retryloop.py | 33 +++++++++++++++++++++++++++++---- tests/test_edgeql_extensions.py | 13 +++++++++++-- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/edb/common/retryloop.py b/edb/common/retryloop.py index be9feed0e70..d6c7d927579 100644 --- a/edb/common/retryloop.py +++ b/edb/common/retryloop.py @@ -52,14 +52,18 @@ def __init__( self, *, backoff: Callable[[int], float] = const_backoff(0.5), - timeout: float, + timeout: float | None = None, + iterations: int | None = None, ignore: Type[Exception] | Tuple[Type[Exception], ...] | None = None, wait_for: Type[Exception] | Tuple[Type[Exception], ...] | None = None, retry_cb: Callable[[Optional[BaseException]], None] | None = None, ) -> None: + assert timeout is not None or iterations is not None + self._iteration = 0 self._backoff = backoff self._timeout = timeout + self._max_iterations = iterations self._ignore = ignore self._wait_for = wait_for self._started_at = 0.0 @@ -113,10 +117,19 @@ async def __aexit__( # Propagate, it's not the error we expected. return False - if elapsed > self._loop._timeout: + if ( + self._loop._timeout is not None + and elapsed > self._loop._timeout + ): # Propagate -- we've run it enough times. return False + if ( + self._loop._max_iterations is not None + and self._loop._iteration >= self._loop._max_iterations + ): + return False + if self._loop._retry_cb is not None: self._loop._retry_cb(e) @@ -137,10 +150,22 @@ async def __aexit__( # Propagate, it's not the error we expected. return False - if elapsed > self._loop._timeout: + if ( + self._loop._timeout is not None + and elapsed > self._loop._timeout + ): + raise TimeoutError( + f'exception matching {self._loop._wait_for!r} ' + f'has not happened in {self._loop._timeout} seconds') + + if ( + self._loop._max_iterations is not None + and self._loop._iteration >= self._loop._max_iterations + ): raise TimeoutError( f'exception matching {self._loop._wait_for!r} ' - f'has not happen in {self._loop._timeout} seconds') + f'has not happened in {self._loop._max_iterations} ' + f'iterations') # Ignore the exception until next run. return True diff --git a/tests/test_edgeql_extensions.py b/tests/test_edgeql_extensions.py index f5e493c1bba..519af18cad5 100644 --- a/tests/test_edgeql_extensions.py +++ b/tests/test_edgeql_extensions.py @@ -984,8 +984,17 @@ async def test_edgeql_extensions_06(self): }; ''') try: - async with self._run_and_rollback(): - await self._extension_test_06b() + # XXX what + from edb.common import retryloop + rloop = retryloop.RetryLoop( + backoff=retryloop.const_backoff(0.0), + iterations=3, + ignore=edgedb.TransactionSerializationError, + ) + async for iteration in rloop: + async with iteration: + async with self._run_and_rollback(): + await self._extension_test_06b() finally: await self.con.execute(''' drop extension package bar VERSION '1.0'; From b43d5c9cbf278f0671e66cb11623febf49ffc302 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Fri, 1 Mar 2024 11:11:33 -0800 Subject: [PATCH 3/7] Revert "wtf... try doing a retry just to see if it helps" This reverts commit 84d004990c2249cfe4f86e853106fef217e613be. --- edb/common/retryloop.py | 33 ++++----------------------------- tests/test_edgeql_extensions.py | 13 ++----------- 2 files changed, 6 insertions(+), 40 deletions(-) diff --git a/edb/common/retryloop.py b/edb/common/retryloop.py index d6c7d927579..be9feed0e70 100644 --- a/edb/common/retryloop.py +++ b/edb/common/retryloop.py @@ -52,18 +52,14 @@ def __init__( self, *, backoff: Callable[[int], float] = const_backoff(0.5), - timeout: float | None = None, - iterations: int | None = None, + timeout: float, ignore: Type[Exception] | Tuple[Type[Exception], ...] | None = None, wait_for: Type[Exception] | Tuple[Type[Exception], ...] | None = None, retry_cb: Callable[[Optional[BaseException]], None] | None = None, ) -> None: - assert timeout is not None or iterations is not None - self._iteration = 0 self._backoff = backoff self._timeout = timeout - self._max_iterations = iterations self._ignore = ignore self._wait_for = wait_for self._started_at = 0.0 @@ -117,19 +113,10 @@ async def __aexit__( # Propagate, it's not the error we expected. return False - if ( - self._loop._timeout is not None - and elapsed > self._loop._timeout - ): + if elapsed > self._loop._timeout: # Propagate -- we've run it enough times. return False - if ( - self._loop._max_iterations is not None - and self._loop._iteration >= self._loop._max_iterations - ): - return False - if self._loop._retry_cb is not None: self._loop._retry_cb(e) @@ -150,22 +137,10 @@ async def __aexit__( # Propagate, it's not the error we expected. return False - if ( - self._loop._timeout is not None - and elapsed > self._loop._timeout - ): - raise TimeoutError( - f'exception matching {self._loop._wait_for!r} ' - f'has not happened in {self._loop._timeout} seconds') - - if ( - self._loop._max_iterations is not None - and self._loop._iteration >= self._loop._max_iterations - ): + if elapsed > self._loop._timeout: raise TimeoutError( f'exception matching {self._loop._wait_for!r} ' - f'has not happened in {self._loop._max_iterations} ' - f'iterations') + f'has not happen in {self._loop._timeout} seconds') # Ignore the exception until next run. return True diff --git a/tests/test_edgeql_extensions.py b/tests/test_edgeql_extensions.py index 519af18cad5..f5e493c1bba 100644 --- a/tests/test_edgeql_extensions.py +++ b/tests/test_edgeql_extensions.py @@ -984,17 +984,8 @@ async def test_edgeql_extensions_06(self): }; ''') try: - # XXX what - from edb.common import retryloop - rloop = retryloop.RetryLoop( - backoff=retryloop.const_backoff(0.0), - iterations=3, - ignore=edgedb.TransactionSerializationError, - ) - async for iteration in rloop: - async with iteration: - async with self._run_and_rollback(): - await self._extension_test_06b() + async with self._run_and_rollback(): + await self._extension_test_06b() finally: await self.con.execute(''' drop extension package bar VERSION '1.0'; From c594d44befff5b2c7f5b48bc10ce8ec850ca22e9 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Wed, 28 Feb 2024 10:57:04 -0800 Subject: [PATCH 4/7] try setting EDGEDB_DEBUG_SERVER --- .github/workflows.src/build.inc.yml | 1 + .github/workflows/dryrun.yml | 10 ++++++++++ .github/workflows/nightly.yml | 10 ++++++++++ .github/workflows/release.yml | 10 ++++++++++ .github/workflows/testing.yml | 10 ++++++++++ 5 files changed, 41 insertions(+) diff --git a/.github/workflows.src/build.inc.yml b/.github/workflows.src/build.inc.yml index b24dc532790..6102ec44c59 100644 --- a/.github/workflows.src/build.inc.yml +++ b/.github/workflows.src/build.inc.yml @@ -208,6 +208,7 @@ # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: << 0 if tgt.runs_on and 'self-hosted' in tgt.runs_on else 1 >> + EDGEDB_DEBUG_SERVER: 1 <%- endfor %> <%- for tgt in targets.macos %> diff --git a/.github/workflows/dryrun.yml b/.github/workflows/dryrun.yml index 272cb0f0dd7..2490b40a7c2 100644 --- a/.github/workflows/dryrun.yml +++ b/.github/workflows/dryrun.yml @@ -1004,6 +1004,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-bullseye-x86_64: needs: [build-debian-bullseye-x86_64] @@ -1046,6 +1047,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-bookworm-x86_64: needs: [build-debian-bookworm-x86_64] @@ -1088,6 +1090,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-bionic-x86_64: needs: [build-ubuntu-bionic-x86_64] @@ -1130,6 +1133,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-focal-x86_64: needs: [build-ubuntu-focal-x86_64] @@ -1172,6 +1176,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-jammy-x86_64: needs: [build-ubuntu-jammy-x86_64] @@ -1214,6 +1219,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-centos-8-x86_64: needs: [build-centos-8-x86_64] @@ -1256,6 +1262,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-rockylinux-9-x86_64: needs: [build-rockylinux-9-x86_64] @@ -1298,6 +1305,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-linux-x86_64: needs: [build-linux-x86_64] @@ -1340,6 +1348,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-linuxmusl-x86_64: needs: [build-linuxmusl-x86_64] @@ -1382,6 +1391,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-macos-x86_64: needs: [build-macos-x86_64] diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 463abe52a15..341bb03033c 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -988,6 +988,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-buster-aarch64: needs: [build-debian-buster-aarch64] @@ -1009,6 +1010,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-bullseye-x86_64: needs: [build-debian-bullseye-x86_64] @@ -1030,6 +1032,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-bullseye-aarch64: needs: [build-debian-bullseye-aarch64] @@ -1051,6 +1054,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-bookworm-x86_64: needs: [build-debian-bookworm-x86_64] @@ -1198,6 +1202,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-jammy-aarch64: needs: [build-ubuntu-jammy-aarch64] @@ -1219,6 +1224,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-centos-8-x86_64: needs: [build-centos-8-x86_64] @@ -1261,6 +1267,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-rockylinux-9-x86_64: needs: [build-rockylinux-9-x86_64] @@ -1303,6 +1310,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-linux-x86_64: needs: [build-linux-x86_64] @@ -1345,6 +1353,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-linuxmusl-x86_64: needs: [build-linuxmusl-x86_64] @@ -1387,6 +1396,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-macos-x86_64: needs: [build-macos-x86_64] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 02f0d26f91e..6dc00ae2472 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -599,6 +599,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-buster-aarch64: needs: [build-debian-buster-aarch64] @@ -619,6 +620,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-bullseye-x86_64: needs: [build-debian-bullseye-x86_64] @@ -699,6 +701,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-bionic-x86_64: needs: [build-ubuntu-bionic-x86_64] @@ -739,6 +742,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-focal-x86_64: needs: [build-ubuntu-focal-x86_64] @@ -779,6 +783,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-jammy-x86_64: needs: [build-ubuntu-jammy-x86_64] @@ -819,6 +824,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-centos-8-x86_64: needs: [build-centos-8-x86_64] @@ -859,6 +865,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-rockylinux-9-x86_64: needs: [build-rockylinux-9-x86_64] @@ -899,6 +906,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-linux-x86_64: needs: [build-linux-x86_64] @@ -939,6 +947,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-linuxmusl-x86_64: needs: [build-linuxmusl-x86_64] @@ -979,6 +988,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-macos-x86_64: needs: [build-macos-x86_64] diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 3731edc94d3..c127e9f2ade 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -622,6 +622,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-buster-aarch64: needs: [build-debian-buster-aarch64] @@ -685,6 +686,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-debian-bookworm-x86_64: needs: [build-debian-bookworm-x86_64] @@ -727,6 +729,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-bionic-x86_64: needs: [build-ubuntu-bionic-x86_64] @@ -769,6 +772,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-focal-x86_64: needs: [build-ubuntu-focal-x86_64] @@ -811,6 +815,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-ubuntu-jammy-x86_64: needs: [build-ubuntu-jammy-x86_64] @@ -853,6 +858,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-centos-8-x86_64: needs: [build-centos-8-x86_64] @@ -895,6 +901,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-rockylinux-9-x86_64: needs: [build-rockylinux-9-x86_64] @@ -937,6 +944,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-linux-x86_64: needs: [build-linux-x86_64] @@ -979,6 +987,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-linuxmusl-x86_64: needs: [build-linuxmusl-x86_64] @@ -1021,6 +1030,7 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 + EDGEDB_DEBUG_SERVER: 1 test-macos-x86_64: needs: [build-macos-x86_64] From 9613282a14f8e6affd2f0260236792422d2e8677 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Wed, 28 Feb 2024 14:26:38 -0800 Subject: [PATCH 5/7] supress SERVER_DEBUG in subtests --- edb/testbase/server.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/edb/testbase/server.py b/edb/testbase/server.py index 40a384508a1..e1dcee11410 100644 --- a/edb/testbase/server.py +++ b/edb/testbase/server.py @@ -2294,7 +2294,10 @@ async def __aenter__(self): await asyncio.wait(pending, timeout=10) if self.proc.returncode is not None: - output = (await self.proc.stdout.read()).decode().strip() + if self.debug: + output = '' + else: + output = (await self.proc.stdout.read()).decode().strip() raise edgedb_cluster.ClusterError(output) else: assert status_task.done() @@ -2344,7 +2347,7 @@ def start_edgedb_server( compiler_pool_size: int=2, compiler_pool_mode: Optional[edgedb_args.CompilerPoolMode] = None, adjacent_to: Optional[tconn.Connection]=None, - debug: bool=debug.flags.server, + debug: bool=False, backend_dsn: Optional[str] = None, runstate_dir: Optional[str] = None, data_dir: Optional[str] = None, From 9bb0a26f4b4589d41e2bd729d48832a343204b9d Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Fri, 1 Mar 2024 11:47:53 -0800 Subject: [PATCH 6/7] Revert "supress SERVER_DEBUG in subtests" This reverts commit 9613282a14f8e6affd2f0260236792422d2e8677. --- edb/testbase/server.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/edb/testbase/server.py b/edb/testbase/server.py index e1dcee11410..40a384508a1 100644 --- a/edb/testbase/server.py +++ b/edb/testbase/server.py @@ -2294,10 +2294,7 @@ async def __aenter__(self): await asyncio.wait(pending, timeout=10) if self.proc.returncode is not None: - if self.debug: - output = '' - else: - output = (await self.proc.stdout.read()).decode().strip() + output = (await self.proc.stdout.read()).decode().strip() raise edgedb_cluster.ClusterError(output) else: assert status_task.done() @@ -2347,7 +2344,7 @@ def start_edgedb_server( compiler_pool_size: int=2, compiler_pool_mode: Optional[edgedb_args.CompilerPoolMode] = None, adjacent_to: Optional[tconn.Connection]=None, - debug: bool=False, + debug: bool=debug.flags.server, backend_dsn: Optional[str] = None, runstate_dir: Optional[str] = None, data_dir: Optional[str] = None, From 2b554eb140478d7941491ea392cf59450908b225 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Fri, 1 Mar 2024 11:48:19 -0800 Subject: [PATCH 7/7] Revert "try setting EDGEDB_DEBUG_SERVER" This reverts commit c594d44befff5b2c7f5b48bc10ce8ec850ca22e9. --- .github/workflows.src/build.inc.yml | 1 - .github/workflows/dryrun.yml | 10 ---------- .github/workflows/nightly.yml | 10 ---------- .github/workflows/release.yml | 10 ---------- .github/workflows/testing.yml | 10 ---------- 5 files changed, 41 deletions(-) diff --git a/.github/workflows.src/build.inc.yml b/.github/workflows.src/build.inc.yml index 6102ec44c59..b24dc532790 100644 --- a/.github/workflows.src/build.inc.yml +++ b/.github/workflows.src/build.inc.yml @@ -208,7 +208,6 @@ # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: << 0 if tgt.runs_on and 'self-hosted' in tgt.runs_on else 1 >> - EDGEDB_DEBUG_SERVER: 1 <%- endfor %> <%- for tgt in targets.macos %> diff --git a/.github/workflows/dryrun.yml b/.github/workflows/dryrun.yml index 2490b40a7c2..272cb0f0dd7 100644 --- a/.github/workflows/dryrun.yml +++ b/.github/workflows/dryrun.yml @@ -1004,7 +1004,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-bullseye-x86_64: needs: [build-debian-bullseye-x86_64] @@ -1047,7 +1046,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-bookworm-x86_64: needs: [build-debian-bookworm-x86_64] @@ -1090,7 +1088,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-bionic-x86_64: needs: [build-ubuntu-bionic-x86_64] @@ -1133,7 +1130,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-focal-x86_64: needs: [build-ubuntu-focal-x86_64] @@ -1176,7 +1172,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-jammy-x86_64: needs: [build-ubuntu-jammy-x86_64] @@ -1219,7 +1214,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-centos-8-x86_64: needs: [build-centos-8-x86_64] @@ -1262,7 +1256,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-rockylinux-9-x86_64: needs: [build-rockylinux-9-x86_64] @@ -1305,7 +1298,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-linux-x86_64: needs: [build-linux-x86_64] @@ -1348,7 +1340,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-linuxmusl-x86_64: needs: [build-linuxmusl-x86_64] @@ -1391,7 +1382,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-macos-x86_64: needs: [build-macos-x86_64] diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 341bb03033c..463abe52a15 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -988,7 +988,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-buster-aarch64: needs: [build-debian-buster-aarch64] @@ -1010,7 +1009,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-bullseye-x86_64: needs: [build-debian-bullseye-x86_64] @@ -1032,7 +1030,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-bullseye-aarch64: needs: [build-debian-bullseye-aarch64] @@ -1054,7 +1051,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-bookworm-x86_64: needs: [build-debian-bookworm-x86_64] @@ -1202,7 +1198,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-jammy-aarch64: needs: [build-ubuntu-jammy-aarch64] @@ -1224,7 +1219,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-centos-8-x86_64: needs: [build-centos-8-x86_64] @@ -1267,7 +1261,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-rockylinux-9-x86_64: needs: [build-rockylinux-9-x86_64] @@ -1310,7 +1303,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-linux-x86_64: needs: [build-linux-x86_64] @@ -1353,7 +1345,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-linuxmusl-x86_64: needs: [build-linuxmusl-x86_64] @@ -1396,7 +1387,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-macos-x86_64: needs: [build-macos-x86_64] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6dc00ae2472..02f0d26f91e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -599,7 +599,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-buster-aarch64: needs: [build-debian-buster-aarch64] @@ -620,7 +619,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-bullseye-x86_64: needs: [build-debian-bullseye-x86_64] @@ -701,7 +699,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-bionic-x86_64: needs: [build-ubuntu-bionic-x86_64] @@ -742,7 +739,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-focal-x86_64: needs: [build-ubuntu-focal-x86_64] @@ -783,7 +779,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-jammy-x86_64: needs: [build-ubuntu-jammy-x86_64] @@ -824,7 +819,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-centos-8-x86_64: needs: [build-centos-8-x86_64] @@ -865,7 +859,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-rockylinux-9-x86_64: needs: [build-rockylinux-9-x86_64] @@ -906,7 +899,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-linux-x86_64: needs: [build-linux-x86_64] @@ -947,7 +939,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-linuxmusl-x86_64: needs: [build-linuxmusl-x86_64] @@ -988,7 +979,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-macos-x86_64: needs: [build-macos-x86_64] diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index c127e9f2ade..3731edc94d3 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -622,7 +622,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-buster-aarch64: needs: [build-debian-buster-aarch64] @@ -686,7 +685,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-debian-bookworm-x86_64: needs: [build-debian-bookworm-x86_64] @@ -729,7 +727,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-bionic-x86_64: needs: [build-ubuntu-bionic-x86_64] @@ -772,7 +769,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-focal-x86_64: needs: [build-ubuntu-focal-x86_64] @@ -815,7 +811,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-ubuntu-jammy-x86_64: needs: [build-ubuntu-jammy-x86_64] @@ -858,7 +853,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-centos-8-x86_64: needs: [build-centos-8-x86_64] @@ -901,7 +895,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-rockylinux-9-x86_64: needs: [build-rockylinux-9-x86_64] @@ -944,7 +937,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-linux-x86_64: needs: [build-linux-x86_64] @@ -987,7 +979,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-linuxmusl-x86_64: needs: [build-linuxmusl-x86_64] @@ -1030,7 +1021,6 @@ jobs: # edb test with -j higher than 1 seems to result in workflow # jobs getting killed arbitrarily by Github. PKG_TEST_JOBS: 0 - EDGEDB_DEBUG_SERVER: 1 test-macos-x86_64: needs: [build-macos-x86_64]