-
-
Notifications
You must be signed in to change notification settings - Fork 57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test: add integration tests against Postgres.js #479
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,7 +53,12 @@ | |
{ | ||
pre-commit.hooks = { | ||
alejandra.enable = true; | ||
typos.enable = true; | ||
typos = { | ||
enable = true; | ||
excludes = [ | ||
"test/integration/" | ||
]; | ||
}; | ||
}; | ||
} | ||
{ | ||
|
@@ -78,20 +83,31 @@ | |
|
||
services.postgres = { | ||
enable = true; | ||
package = pkgs.postgresql_15; | ||
initialScript = '' | ||
${builtins.readFile ./dev/postgres/00-setup.sql} | ||
|
||
CREATE USER postgres SUPERUSER PASSWORD 'postgres'; | ||
''; | ||
listen_addresses = "127.0.0.1"; | ||
port = 6432; | ||
settings = { | ||
max_prepared_transactions = 262143; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is maximal possible value, in tests I have set it to |
||
}; | ||
}; | ||
|
||
process.implementation = "honcho"; | ||
|
||
# Force connection through TCP instead of Unix socket | ||
env.PGHOST = lib.mkForce ""; | ||
} | ||
{ | ||
languages.javascript = { | ||
enable = true; | ||
bun.enable = true; | ||
yarn.enable = true; | ||
}; | ||
} | ||
({ | ||
pkgs, | ||
lib, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
defmodule Supavisor.Integration.ExternalTest do | ||
use ExUnit.Case, async: false | ||
|
||
@moduletag integration: true | ||
|
||
setup_all do | ||
npm = | ||
get_tool("yarn") || get_tool("npm") || get_tool("bun") || | ||
raise "Cannot find neither Yarn nor NPM" | ||
|
||
assert {_, 0} = System.cmd(npm, ~w[install], cd: suite("js")) | ||
|
||
{:ok, npm: npm} | ||
end | ||
|
||
setup :external_id | ||
|
||
setup ctx do | ||
if get_tool(ctx.runtime) do | ||
:ok | ||
else | ||
raise "Runtime not available" | ||
end | ||
end | ||
|
||
describe "Postgres.js" do | ||
@describetag library: "postgres.js", suite: "js" | ||
|
||
@tag runtime: "node", mode: "session" | ||
test "Node session", ctx do | ||
assert_run(ctx, ~w[postgres/index.js]) | ||
end | ||
|
||
@tag runtime: "node", mode: "transaction" | ||
test "Node transaction", ctx do | ||
assert_run(ctx, ~w[postgres/index.js]) | ||
end | ||
|
||
# These currently do not pass | ||
# @tag runtime: "bun", mode: "session" | ||
# test "Bun session", ctx do | ||
# assert_run ctx, ~w[postgres/index.js], suite: "js" | ||
# end | ||
# | ||
# @tag runtime: "bun", mode: "transaction" | ||
# test "Bun transaction", ctx do | ||
# assert_run ctx, ~w[postgres/index.js], suite: "js" | ||
# end | ||
# | ||
# @tag runtime: "deno", mode: "session" | ||
# test "Deno session", ctx do | ||
# assert_run ctx, ~w[run --allow-all postgres/index.js], suite: "js" | ||
# end | ||
# | ||
# @tag runtime: "deno", mode: "transaction" | ||
# test "Deno transaction", ctx do | ||
# assert_run ctx, ~w[run --allow-all postgres/index.js], suite: "js" | ||
# end | ||
end | ||
|
||
defp assert_run(ctx, args, opts \\ []) do | ||
suite = suite(ctx.suite) | ||
|
||
env = | ||
[ | ||
{"PGMODE", ctx.mode}, | ||
{"PGDATABASE", ctx.db}, | ||
{"PGHOST", "localhost"}, | ||
{"PGPORT", to_string(port(ctx.mode))}, | ||
{"PGUSER", ctx.user}, | ||
{"PGPASS", "postgres"} | ||
] ++ (opts[:env] || []) | ||
|
||
assert {output, code} = | ||
System.cmd(ctx.runtime, args, | ||
env: env, | ||
cd: suite, | ||
stderr_to_stdout: true | ||
) | ||
|
||
assert code == 0, output | ||
end | ||
|
||
## UTILS | ||
|
||
defp suite(name), do: Path.join(__DIR__, name) | ||
|
||
defp get_tool(name), do: System.find_executable(name) | ||
|
||
defp port("session"), do: Application.fetch_env!(:supavisor, :proxy_port_session) | ||
defp port("transaction"), do: Application.fetch_env!(:supavisor, :proxy_port_transaction) | ||
|
||
defp external_id(ctx) do | ||
external_id = | ||
[ctx.runtime, ctx.library, ctx.mode] | ||
|> Enum.map_join("_", &String.replace(&1, ~r/\W/, "")) | ||
|
||
# Ensure that there are no leftovers | ||
_ = Supavisor.Tenants.delete_tenant_by_external_id(external_id) | ||
|
||
_ = Supavisor.Repo.query("DROP DATABASE IF EXISTS #{external_id}") | ||
assert {:ok, _} = Supavisor.Repo.query("CREATE DATABASE #{external_id}") | ||
|
||
assert {:ok, tenant} = | ||
Supavisor.Tenants.create_tenant(%{ | ||
default_parameter_status: %{}, | ||
db_host: "localhost", | ||
db_port: 6432, | ||
db_database: external_id, | ||
auth_query: "SELECT rolname, rolpassword FROM pg_authid WHERE rolname=$1;", | ||
external_id: external_id, | ||
users: [ | ||
%{ | ||
"pool_size" => 3, | ||
"db_user" => "postgres", | ||
"db_password" => "postgres", | ||
"is_manager" => true, | ||
"mode_type" => "session" | ||
} | ||
] | ||
}) | ||
|
||
{:ok, user: "postgres.#{external_id}", db: tenant.db_database, external_id: external_id} | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/node_modules |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"name": "supavisor-integration", | ||
"version": "1.0.0", | ||
"main": "index.js", | ||
"type": "module", | ||
"license": "MIT", | ||
"scripts": { | ||
"test:postgres": "node ./postgres/index.js" | ||
}, | ||
"dependencies": { | ||
"postgres": "^3.4.5" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
1 2 3 | ||
4 5 6 | ||
Comment on lines
+1
to
+2
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does it do? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No idea, it is copied as is from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's try to run it without this file :D There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have found that it is used in one test: t('Copy from file', async() => {
await sql`create table test (x int, y int, z int)`
await new Promise(async r => fs
.createReadStream(rel('copy.csv'))
.pipe(await sql`copy test from stdin`.writable())
.on('finish', r)
)
return [
JSON.stringify(await sql`select * from test`),
'[{"x":1,"y":2,"z":3},{"x":4,"y":5,"z":6}]',
await sql`drop table test`
]
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wondering if we want to put these versions in the env vars
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be useful, but as a separate PR. There I simply copied what we have in other steps.