Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ jobs:
MYSQL_PASSWORD: with_advisory_pass
MYSQL_DATABASE: with_advisory_lock_test
MYSQL_ROOT_HOST: '%'
mariadb:
image: mariadb:12
ports:
- 3306
env:
MARIADB_ROOT_PASSWORD: root
MARIADB_DATABASE: with_advisory_lock_trilogy_test
MARIADB_USER: with_advisory
MARIADB_PASSWORD: with_advisory_pass
MARIADB_ROOT_HOST: '%'
strategy:
fail-fast: false
matrix:
Expand All @@ -60,10 +70,13 @@ jobs:
bundler-cache: true
rubygems: latest


- name: Setup test databases
timeout-minutes: 5
env:
DATABASE_URL_PG: postgres://with_advisory:with_advisory_pass@localhost:${{ job.services.postgres.ports[5432] }}/with_advisory_lock_test
DATABASE_URL_MYSQL: mysql2://with_advisory:with_advisory_pass@127.0.0.1:${{ job.services.mysql.ports[3306] }}/with_advisory_lock_test
DATABASE_URL_TRILOGY: trilogy://with_advisory:with_advisory_pass@127.0.0.1:${{ job.services.mariadb.ports[3306] }}/with_advisory_lock_trilogy_test
run: |
cd test/dummy
bundle exec rake db:test:prepare
Expand All @@ -72,5 +85,6 @@ jobs:
env:
DATABASE_URL_PG: postgres://with_advisory:with_advisory_pass@localhost:${{ job.services.postgres.ports[5432] }}/with_advisory_lock_test
DATABASE_URL_MYSQL: mysql2://with_advisory:with_advisory_pass@127.0.0.1:${{ job.services.mysql.ports[3306] }}/with_advisory_lock_test
DATABASE_URL_TRILOGY: trilogy://with_advisory:with_advisory_pass@127.0.0.1:${{ job.services.mariadb.ports[3306] }}/with_advisory_lock_trilogy_test
WITH_ADVISORY_LOCK_PREFIX: ${{ github.run_id }}
run: bin/rails test
5 changes: 5 additions & 0 deletions test/dummy/app/models/trilogy_label.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

class TrilogyLabel < TrilogyRecord
self.table_name = 'trilogy_labels'
end
6 changes: 6 additions & 0 deletions test/dummy/app/models/trilogy_record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

class TrilogyRecord < ActiveRecord::Base
self.abstract_class = true
establish_connection :trilogy
end
10 changes: 10 additions & 0 deletions test/dummy/app/models/trilogy_tag.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

class TrilogyTag < TrilogyRecord
self.table_name = 'trilogy_tags'

after_save do
TrilogyTagAudit.create(tag_name: name)
TrilogyLabel.create(name: name)
end
end
5 changes: 5 additions & 0 deletions test/dummy/app/models/trilogy_tag_audit.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

class TrilogyTagAudit < TrilogyRecord
self.table_name = 'trilogy_tag_audits'
end
6 changes: 6 additions & 0 deletions test/dummy/config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ test:
url: "<%= ENV['DATABASE_URL_MYSQL'] %>"
properties:
allowPublicKeyRetrieval: true
trilogy:
<<: *default
url: "<%= ENV['DATABASE_URL_TRILOGY'] %>"
adapter: trilogy
properties:
allowPublicKeyRetrieval: true
15 changes: 15 additions & 0 deletions test/dummy/db/trilogy_schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

ActiveRecord::Schema.define(version: 1) do
create_table 'trilogy_tags', force: true do |t|
t.string 'name'
end

create_table 'trilogy_tag_audits', id: false, force: true do |t|
t.string 'tag_name'
end

create_table 'trilogy_labels', id: false, force: true do |t|
t.string 'name'
end
end
36 changes: 36 additions & 0 deletions test/dummy/lib/tasks/trilogy.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

namespace :db do
namespace :trilogy do
desc 'Create and load the Trilogy database schema'
task prepare: :environment do
ActiveRecord::Base.establish_connection(:trilogy)

# Load the schema
load Rails.root.join('db', 'trilogy_schema.rb')

puts 'Trilogy database schema loaded successfully'
rescue StandardError => e
puts "Error loading Trilogy schema: #{e.message}"
raise e
end
end

namespace :test do
task prepare: :environment do
# Setup PostgreSQL database
ActiveRecord::Base.establish_connection(:primary)
load Rails.root.join('db', 'schema.rb')

# Setup MySQL database
ActiveRecord::Base.establish_connection(:secondary)
load Rails.root.join('db', 'secondary_schema.rb')

# Setup Trilogy database
ActiveRecord::Base.establish_connection(:trilogy)
load Rails.root.join('db', 'trilogy_schema.rb')

puts 'All test databases prepared successfully'
end
end
end
42 changes: 37 additions & 5 deletions test/sanity_check_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require 'test_helper'

class SanityCheckTest < GemTestCase
test 'PostgreSQL and MySQL databases are properly isolated' do
test 'PostgreSQL, MySQL, and Trilogy databases are properly isolated' do
# Create a tag in PostgreSQL database
pg_tag = Tag.create!(name: 'postgresql-only-tag')

Expand All @@ -26,9 +26,31 @@ class SanityCheckTest < GemTestCase
assert_not Tag.exists?(name: 'mysql-only-tag')
assert_equal 0, Tag.where(name: 'mysql-only-tag').count

# Create a tag in Trilogy database
trilogy_tag = TrilogyTag.create!(name: 'trilogy-only-tag')

# Verify it exists in Trilogy
assert TrilogyTag.exists?(name: 'trilogy-only-tag')
assert_equal 1, TrilogyTag.where(name: 'trilogy-only-tag').count

# Verify it does NOT exist in PostgreSQL or MySQL databases
assert_not Tag.exists?(name: 'trilogy-only-tag')
assert_equal 0, Tag.where(name: 'trilogy-only-tag').count
assert_not MysqlTag.exists?(name: 'trilogy-only-tag')
assert_equal 0, MysqlTag.where(name: 'trilogy-only-tag').count

# Verify PostgreSQL tag does NOT exist in Trilogy
assert_not TrilogyTag.exists?(name: 'postgresql-only-tag')
assert_equal 0, TrilogyTag.where(name: 'postgresql-only-tag').count

# Verify MySQL tag does NOT exist in Trilogy
assert_not TrilogyTag.exists?(name: 'mysql-only-tag')
assert_equal 0, TrilogyTag.where(name: 'mysql-only-tag').count

# Clean up
pg_tag.destroy
mysql_tag.destroy
trilogy_tag.destroy
end

test 'PostgreSQL models use PostgreSQL adapter' do
Expand All @@ -43,21 +65,31 @@ class SanityCheckTest < GemTestCase
assert_equal 'Mysql2', MysqlLabel.connection.adapter_name
end

test 'can write to both databases in same test' do
# Create records in both databases
test 'Trilogy models use Trilogy adapter' do
assert_equal 'Trilogy', TrilogyTag.connection.adapter_name
assert_equal 'Trilogy', TrilogyTagAudit.connection.adapter_name
assert_equal 'Trilogy', TrilogyLabel.connection.adapter_name
end

test 'can write to all three databases in same test' do
# Create records in all three databases
pg_tag = Tag.create!(name: 'test-pg')
mysql_tag = MysqlTag.create!(name: 'test-mysql')
trilogy_tag = TrilogyTag.create!(name: 'test-trilogy')

# Both should have IDs
# All should have IDs
assert pg_tag.persisted?
assert mysql_tag.persisted?
assert trilogy_tag.persisted?

# IDs should be independent (both could be 1 if tables are empty)
# IDs should be independent (all could be 1 if tables are empty)
assert_kind_of Integer, pg_tag.id
assert_kind_of Integer, mysql_tag.id
assert_kind_of Integer, trilogy_tag.id

# Clean up
pg_tag.destroy
mysql_tag.destroy
trilogy_tag.destroy
end
end
2 changes: 1 addition & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class GemTestCase < ActiveSupport::TestCase

def self.startup
# Validate environment variables when tests actually start running
%w[DATABASE_URL_PG DATABASE_URL_MYSQL].each do |var|
%w[DATABASE_URL_PG DATABASE_URL_MYSQL DATABASE_URL_TRILOGY].each do |var|
abort "Missing required environment variable: #{var}" if ENV[var].nil? || ENV[var].empty?
end
end
Expand Down
24 changes: 23 additions & 1 deletion test/with_advisory_lock/multi_adapter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,37 @@
require 'test_helper'

class MultiAdapterIsolationTest < GemTestCase
test 'postgresql and mysql adapters do not overlap' do
test 'postgresql, mysql, and trilogy adapters do not overlap' do
lock_name = 'multi-adapter-lock'

# PostgreSQL lock doesn't block MySQL
Tag.with_advisory_lock(lock_name) do
assert MysqlTag.with_advisory_lock(lock_name, timeout_seconds: 0) { true }
end

# MySQL lock doesn't block PostgreSQL
MysqlTag.with_advisory_lock(lock_name) do
assert Tag.with_advisory_lock(lock_name, timeout_seconds: 0) { true }
end

# PostgreSQL lock doesn't block Trilogy
Tag.with_advisory_lock(lock_name) do
assert TrilogyTag.with_advisory_lock(lock_name, timeout_seconds: 0) { true }
end

# Trilogy lock doesn't block PostgreSQL
TrilogyTag.with_advisory_lock(lock_name) do
assert Tag.with_advisory_lock(lock_name, timeout_seconds: 0) { true }
end

# MySQL lock doesn't block Trilogy
MysqlTag.with_advisory_lock(lock_name) do
assert TrilogyTag.with_advisory_lock(lock_name, timeout_seconds: 0) { true }
end

# Trilogy lock doesn't block MySQL
TrilogyTag.with_advisory_lock(lock_name) do
assert MysqlTag.with_advisory_lock(lock_name, timeout_seconds: 0) { true }
end
end
end
8 changes: 8 additions & 0 deletions test/with_advisory_lock/parallelism_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,11 @@ def model_class
MysqlTag
end
end

class TrilogyParallelismTest < GemTestCase
include ParallelismTestCases

def model_class
TrilogyTag
end
end
26 changes: 26 additions & 0 deletions test/with_advisory_lock/shared_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,29 @@ class MySQLSharedLocksTest < GemTestCase
assert_match(/shared locks are not supported/, exception.message)
end
end

class TrilogySharedLocksTest < GemTestCase
self.use_transactional_tests = false

test 'does not allow two exclusive locks' do
one = SharedTestWorker.new(TrilogyTag, false)
assert_predicate(one, :locked?)

two = SharedTestWorker.new(TrilogyTag, false)
refute(two.locked?)

one.cleanup!
two.cleanup!
end

test 'raises an error when attempting to use a shared lock' do
one = SharedTestWorker.new(TrilogyTag, true)
assert_equal(false, one.locked?)

exception = assert_raises(ArgumentError) do
one.cleanup!
end

assert_match(/shared locks are not supported/, exception.message)
end
end
8 changes: 8 additions & 0 deletions test/with_advisory_lock/thread_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,11 @@ def model_class
MysqlTag
end
end

class TrilogyThreadTest < GemTestCase
include ThreadTestCases

def model_class
TrilogyTag
end
end
Loading