Skip to content

Commit 8f74216

Browse files
committed
fixup! testing: Add a system-postgres mode for faster testing
1 parent 4841a58 commit 8f74216

File tree

1 file changed

+83
-51
lines changed
  • contrib/pyln-testing/pyln/testing

1 file changed

+83
-51
lines changed

contrib/pyln-testing/pyln/testing/db.py

Lines changed: 83 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,18 @@ def __init__(self, path: str) -> None:
2626
self.provider = None
2727

2828
def get_dsn(self) -> None:
29-
"""SQLite3 doesn't provide a DSN, resulting in no CLI-option.
30-
"""
29+
"""SQLite3 doesn't provide a DSN, resulting in no CLI-option."""
3130
return None
3231

33-
def query(self, query: str) -> Union[List[Dict[str, Union[int, bytes]]], List[Dict[str, Optional[int]]], List[Dict[str, str]], List[Dict[str, Union[str, int]]], List[Dict[str, int]]]:
32+
def query(
33+
self, query: str
34+
) -> Union[
35+
List[Dict[str, Union[int, bytes]]],
36+
List[Dict[str, Optional[int]]],
37+
List[Dict[str, str]],
38+
List[Dict[str, Union[str, int]]],
39+
List[Dict[str, int]],
40+
]:
3441
orig = os.path.join(self.path)
3542
copy = self.path + ".copy"
3643
shutil.copyfile(orig, copy)
@@ -69,22 +76,23 @@ def wipe_db(self):
6976

7077

7178
class PostgresDb(BaseDb):
72-
def __init__(self, dbname, port):
79+
def __init__(self, dbname, hostname, port, username, password):
7380
self.dbname = dbname
7481
self.port = port
7582
self.provider = None
83+
self.hostname = hostname
84+
self.username = username
85+
self.password = password
7686

77-
self.conn = psycopg2.connect("dbname={dbname} user=postgres host=localhost port={port}".format(
78-
dbname=dbname, port=port
79-
))
87+
self.conn = psycopg2.connect(
88+
f"dbname={dbname} user={username} password={password} host={hostname} port={port}"
89+
)
8090
cur = self.conn.cursor()
81-
cur.execute('SELECT 1')
91+
cur.execute("SELECT 1")
8292
cur.close()
8393

8494
def get_dsn(self):
85-
return "postgres://postgres:password@localhost:{port}/{dbname}".format(
86-
port=self.port, dbname=self.dbname
87-
)
95+
return f"postgres://{self.username}:{self.password}@{self.hostname}:{self.port}/{self.dbname}"
8896

8997
def query(self, query):
9098
cur = self.conn.cursor()
@@ -106,10 +114,11 @@ def execute(self, query):
106114
cur.execute(query)
107115

108116
def stop(self):
109-
"""Clean up the database.
110-
"""
117+
"""Clean up the database."""
111118
self.conn.close()
112-
conn = psycopg2.connect("dbname=postgres user=postgres host=localhost port={self.port}")
119+
conn = psycopg2.connect(
120+
f"dbname=postgres user={self.username} host={self.hostname} password={self.password} port={self.port}"
121+
)
113122
cur = conn.cursor()
114123
cur.execute("DROP DATABASE {};".format(self.dbname))
115124
cur.close()
@@ -130,10 +139,7 @@ def start(self) -> None:
130139
pass
131140

132141
def get_db(self, node_directory: str, testname: str, node_id: int) -> Sqlite3Db:
133-
path = os.path.join(
134-
node_directory,
135-
'lightningd.sqlite3'
136-
)
142+
path = os.path.join(node_directory, "lightningd.sqlite3")
137143
return Sqlite3Db(path)
138144

139145
def stop(self) -> None:
@@ -145,69 +151,92 @@ def __init__(self, directory):
145151
self.directory = directory
146152
self.port = None
147153
self.proc = None
154+
self.hostname = "127.0.0.1" # We default to localhost, but can be overridden
155+
self.username = "postgres"
156+
self.password = "postgres"
157+
148158
print("Starting PostgresDbProvider")
149159

150160
def locate_path(self):
151161
# Use `pg_config` to determine correct PostgreSQL installation
152-
pg_config = shutil.which('pg_config')
162+
pg_config = shutil.which("pg_config")
153163
if not pg_config:
154-
raise ValueError("Could not find `pg_config` to determine PostgreSQL binaries. Is PostgreSQL installed?")
164+
raise ValueError(
165+
"Could not find `pg_config` to determine PostgreSQL binaries. Is PostgreSQL installed?"
166+
)
155167

156-
bindir = subprocess.check_output([pg_config, '--bindir']).decode().rstrip()
168+
bindir = subprocess.check_output([pg_config, "--bindir"]).decode().rstrip()
157169
if not os.path.isdir(bindir):
158-
raise ValueError("Error: `pg_config --bindir` didn't return a proper path: {}".format(bindir))
159-
160-
initdb = os.path.join(bindir, 'initdb')
161-
postgres = os.path.join(bindir, 'postgres')
170+
raise ValueError(
171+
"Error: `pg_config --bindir` didn't return a proper path: {}".format(
172+
bindir
173+
)
174+
)
175+
176+
initdb = os.path.join(bindir, "initdb")
177+
postgres = os.path.join(bindir, "postgres")
162178
if os.path.isfile(initdb) and os.path.isfile(postgres):
163179
if os.access(initdb, os.X_OK) and os.access(postgres, os.X_OK):
164180
logging.info("Found `postgres` and `initdb` in {}".format(bindir))
165181
return initdb, postgres
166182

167-
raise ValueError("Could not find `postgres` and `initdb` binaries in {}".format(bindir))
183+
raise ValueError(
184+
"Could not find `postgres` and `initdb` binaries in {}".format(bindir)
185+
)
168186

169187
def start(self):
170188
passfile = os.path.join(self.directory, "pgpass.txt")
171189
# Need to write a tiny file containing the password so `initdb` can
172190
# pick it up
173-
with open(passfile, 'w') as f:
174-
f.write('cltest\n')
191+
with open(passfile, "w") as f:
192+
f.write("cltest\n")
175193

176194
# Look for a postgres directory that isn't taken yet. Not locking
177195
# since this is run in a single-threaded context, at the start of each
178196
# test. Multiple workers have separate directories, so they can't
179197
# trample each other either.
180198
for i in itertools.count():
181-
self.pgdir = os.path.join(self.directory, 'pgsql-{}'.format(i))
199+
self.pgdir = os.path.join(self.directory, "pgsql-{}".format(i))
182200
if not os.path.exists(self.pgdir):
183201
break
184202

185203
initdb, postgres = self.locate_path()
186-
subprocess.check_call([
187-
initdb,
188-
'--pwfile={}'.format(passfile),
189-
'--pgdata={}'.format(self.pgdir),
190-
'--auth=trust',
191-
'--username=postgres',
192-
])
193-
conffile = os.path.join(self.pgdir, 'postgresql.conf')
194-
with open(conffile, 'a') as f:
195-
f.write('max_connections = 1000\nshared_buffers = 240MB\n')
204+
subprocess.check_call(
205+
[
206+
initdb,
207+
"--pwfile={}".format(passfile),
208+
"--pgdata={}".format(self.pgdir),
209+
"--auth=trust",
210+
"--username=postgres",
211+
]
212+
)
213+
conffile = os.path.join(self.pgdir, "postgresql.conf")
214+
with open(conffile, "a") as f:
215+
f.write("max_connections = 1000\nshared_buffers = 240MB\n")
196216

197217
self.port = reserve_unused_port()
198-
self.proc = subprocess.Popen([
199-
postgres,
200-
'-k', '/tmp/', # So we don't use /var/lib/...
201-
'-D', self.pgdir,
202-
'-p', str(self.port),
203-
'-F',
204-
'-i',
205-
])
218+
self.proc = subprocess.Popen(
219+
[
220+
postgres,
221+
"-k",
222+
"/tmp/", # So we don't use /var/lib/...
223+
"-D",
224+
self.pgdir,
225+
"-p",
226+
str(self.port),
227+
"-F",
228+
"-i",
229+
]
230+
)
206231
# Hacky but seems to work ok (might want to make the postgres proc a
207232
# TailableProc as well if too flaky).
208233
for i in range(30):
209234
try:
210-
self.conn = psycopg2.connect("dbname=template1 user=postgres host=localhost port={}".format(self.port))
235+
self.conn = psycopg2.connect(
236+
"dbname=template1 user=postgres host=localhost port={}".format(
237+
self.port
238+
)
239+
)
211240
break
212241
except Exception:
213242
time.sleep(0.5)
@@ -217,13 +246,15 @@ def start(self):
217246

218247
def get_db(self, node_directory, testname, node_id):
219248
# Random suffix to avoid collisions on repeated tests
220-
nonce = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(8))
249+
nonce = "".join(
250+
random.choice(string.ascii_lowercase + string.digits) for _ in range(8)
251+
)
221252
dbname = "{}_{}_{}".format(testname, node_id, nonce)
222253

223254
cur = self.conn.cursor()
224255
cur.execute("CREATE DATABASE {};".format(dbname))
225256
cur.close()
226-
db = PostgresDb(dbname, self.port)
257+
db = PostgresDb(dbname, self.hostname, self.port, self.username, self.password)
227258
return db
228259

229260
def stop(self):
@@ -275,7 +306,8 @@ def __init__(self, directory):
275306

276307
self.hostname = parts.hostname
277308
self.username = parts.username
278-
self.port = parts.port
309+
self.password = parts.password if parts.password else ""
310+
self.port = parts.port if parts.port else 5432
279311
self.dbname = parts.path
280312

281313
def stop(self):

0 commit comments

Comments
 (0)