caruby-tissue 1.3.1 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/README.md +6 -0
- data/lib/catissue/annotation/annotation_class.rb +1 -1
- data/lib/catissue/cli/migrate.rb +1 -0
- data/lib/catissue/domain/container.rb +13 -8
- data/lib/catissue/domain/specimen.rb +9 -3
- data/lib/catissue/domain/specimen_event_parameters.rb +1 -8
- data/lib/catissue/domain/specimen_requirement.rb +1 -1
- data/lib/catissue/domain/storage_container.rb +4 -3
- data/lib/catissue/domain/uniquify.rb +82 -0
- data/lib/catissue/migration/migrator.rb +15 -7
- data/lib/catissue/migration/uniquify.rb +2 -111
- data/lib/catissue/util/position.rb +14 -2
- data/lib/catissue/version.rb +1 -1
- data/test/fixtures/catissue/domain/conf/catissue_override.yaml +9 -0
- data/test/fixtures/catissue/extract/conf/scg_extract.yaml +3 -0
- data/test/fixtures/catissue/extract/conf/scg_fields.yaml +3 -0
- data/test/fixtures/catissue/extract/conf/spc_extract.yaml +3 -0
- data/test/fixtures/catissue/extract/conf/spc_fields.yaml +4 -0
- data/test/fixtures/lib/catissue/defaults_test_fixture.rb +202 -0
- data/test/lib/catissue/database/controlled_values_test.rb +47 -0
- data/test/lib/catissue/database/database_test.rb +28 -0
- data/test/lib/catissue/domain/address_test.rb +53 -0
- data/test/lib/catissue/domain/base_haemotology_pathology_test.rb +25 -0
- data/test/lib/catissue/domain/ca_tissue_test_defaults_test.rb +27 -0
- data/test/lib/catissue/domain/capacity_test.rb +12 -0
- data/test/lib/catissue/domain/collection_event_parameters_test.rb +24 -0
- data/test/lib/catissue/domain/collection_protocol_event_test.rb +25 -0
- data/test/lib/catissue/domain/collection_protocol_registration_test.rb +71 -0
- data/test/lib/catissue/domain/collection_protocol_test.rb +69 -0
- data/test/lib/catissue/domain/container_position_test.rb +29 -0
- data/test/lib/catissue/domain/department_test.rb +21 -0
- data/test/lib/catissue/domain/disposal_event_parameters_test.rb +16 -0
- data/test/lib/catissue/domain/location_test.rb +38 -0
- data/test/lib/catissue/domain/metadata_test.rb +62 -0
- data/test/lib/catissue/domain/participant_medical_identifier_test.rb +26 -0
- data/test/lib/catissue/domain/participant_test.rb +96 -0
- data/test/lib/catissue/domain/site_test.rb +30 -0
- data/test/lib/catissue/domain/specimen_array_test.rb +38 -0
- data/test/lib/catissue/domain/specimen_array_type_test.rb +27 -0
- data/test/lib/catissue/domain/specimen_characteristics_test.rb +15 -0
- data/test/lib/catissue/domain/specimen_collection_group_test.rb +216 -0
- data/test/lib/catissue/domain/specimen_event_parameters_test.rb +61 -0
- data/test/lib/catissue/domain/specimen_position_test.rb +62 -0
- data/test/lib/catissue/domain/specimen_requirement_test.rb +61 -0
- data/test/lib/catissue/domain/specimen_test.rb +272 -0
- data/test/lib/catissue/domain/storage_container_test.rb +150 -0
- data/test/lib/catissue/domain/storage_type_test.rb +70 -0
- data/test/lib/catissue/domain/transfer_event_parameters_test.rb +38 -0
- data/test/lib/catissue/domain/user_test.rb +50 -0
- data/test/lib/catissue/extract/delta_test.rb +25 -0
- data/test/lib/catissue/extract/extractor_test.rb +43 -0
- data/test/lib/catissue/import/importable_module_test.rb +14 -0
- data/test/lib/catissue/migration/test_case.rb +103 -0
- data/test/lib/catissue/test_case.rb +225 -0
- data/test/lib/examples/galena/domain/examples_test.rb +70 -0
- data/test/lib/examples/galena/migration/catissue.log +0 -0
- data/test/lib/examples/galena/migration/filter_test.rb +26 -0
- data/test/lib/examples/galena/migration/frozen_test.rb +28 -0
- data/test/lib/examples/galena/migration/general_test.rb +44 -0
- data/test/lib/examples/galena/migration/simple_test.rb +29 -0
- data/test/lib/examples/galena/migration/test_case.rb +52 -0
- data/test/lib/examples/galena/migration/uniquify.rb +93 -0
- metadata +223 -184
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_case')
|
2
|
+
require 'caruby/util/uniquifier'
|
3
|
+
require 'test/fixtures/lib/catissue/defaults_test_fixture'
|
4
|
+
|
5
|
+
class StorageTypeTest < Test::Unit::TestCase
|
6
|
+
include CaTissue::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
super
|
10
|
+
@spc = defaults.specimen
|
11
|
+
@frz_type = CaTissue::StorageType.new(:name => 'Freezer'.uniquify, :columns => 5, :rows => 5)
|
12
|
+
@rack_type = CaTissue::StorageType.new(:name => 'Rack'.uniquify, :columns => 1, :rows => 1)
|
13
|
+
@box_type = CaTissue::StorageType.new(:name => 'Box'.uniquify, :columns => 1, :rows => 1)
|
14
|
+
@array_type = CaTissue::SpecimenArrayType.new(:name => 'SpecimenArray'.uniquify,
|
15
|
+
:specimen_class => @spc.specimen_class, :specimen_types => [@spc.specimen_type],
|
16
|
+
:columns => 5, :rows => 5)
|
17
|
+
@frz_type << @rack_type
|
18
|
+
@rack_type << @box_type
|
19
|
+
@box_type << @array_type << @spc.specimen_class
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_defaults
|
23
|
+
verify_defaults(@frz_type)
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_create_container
|
27
|
+
frz = @frz_type.create_container
|
28
|
+
assert_same(CaTissue::StorageContainer, frz.class, "Created instance class incorrect")
|
29
|
+
assert_same(@frz_type, frz.container_type, "Created container type incorrect")
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_can_hold
|
33
|
+
assert(@frz_type.can_hold_child?(@rack_type.create_container), "Freezer can't hold a rack")
|
34
|
+
assert(@rack_type.can_hold_child?(@box_type.create_container), "Rack can't hold a box")
|
35
|
+
assert(@box_type.can_hold_child?(@array_type.create_container), "Box can't hold an array")
|
36
|
+
assert(@array_type.can_hold_child?(@spc), "Array can't hold the specimen")
|
37
|
+
assert(@box_type.can_hold_child?(@spc), "Box can't hold the specimen")
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_comparison
|
41
|
+
assert_equal(@frz_type, @frz_type, "Same not equal")
|
42
|
+
assert_equal(@frz_type, @frz_type.copy(:name), "Name not used in equality")
|
43
|
+
assert(@rack_type < @frz_type, "Rack type not < freezer type")
|
44
|
+
assert(@frz_type > @rack_type, "Freezer type not > rack type")
|
45
|
+
assert(@box_type < @rack_type, "Box type not < rack type")
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_closure
|
49
|
+
assert_equal([@frz_type, @rack_type, @box_type], @frz_type.closure, "Freezer type closure incorrect")
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_path_to
|
53
|
+
assert_equal([@frz_type, @rack_type, @box_type], @frz_type.path_to(@spc), "Freezer path to specimen incorrect")
|
54
|
+
end
|
55
|
+
|
56
|
+
## DATABASE TESTS ##
|
57
|
+
|
58
|
+
def test_save
|
59
|
+
verify_save(@box_type)
|
60
|
+
assert(@box_type.find_containers.empty?, "Box incorrectly found")
|
61
|
+
site = defaults.tissue_bank
|
62
|
+
box = @box_type.find_available(site)
|
63
|
+
assert_nil(box, "Available box incorrectly created")
|
64
|
+
box = @box_type.find_available(site, :create)
|
65
|
+
assert_not_nil(box, "Available box not created")
|
66
|
+
assert_not_nil(box.identifier, "Available box missing identifier")
|
67
|
+
stored = @box_type.find_containers.map { |ctr| ctr.identifier}
|
68
|
+
assert_equal([box.identifier], stored, "Box with identifier #{box.identifier} not found")
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_case')
|
2
|
+
require 'test/fixtures/lib/catissue/defaults_test_fixture'
|
3
|
+
require 'caruby/database/store_template_builder'
|
4
|
+
|
5
|
+
class TransferEventParametersTest < Test::Unit::TestCase
|
6
|
+
include CaTissue::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
super
|
10
|
+
spc = defaults.specimen
|
11
|
+
defaults.box << spc
|
12
|
+
@xfr = CaTissue::TransferEventParameters.new(:specimen => spc, :to => spc.location)
|
13
|
+
end
|
14
|
+
|
15
|
+
# def test_inverse_setter
|
16
|
+
# assert(@xfr.specimen.event_parameters.include?(@xfr), "EventParameters not found in specimen")
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def test_defaults
|
20
|
+
# verify_defaults(@xfr)
|
21
|
+
# end
|
22
|
+
|
23
|
+
# def test_save
|
24
|
+
# verify_save(@xfr)
|
25
|
+
# shift(@xfr)
|
26
|
+
# verify_save(@xfr)
|
27
|
+
# end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Resets the given CaTissue::TransferEventParameters xfr so that +from+ is the
|
32
|
+
# old +to+, +to+ is the next location, and the identifier is cleared.
|
33
|
+
def shift(xfr)
|
34
|
+
xfr.from = xfr.to
|
35
|
+
xfr.to = xfr.from.succ
|
36
|
+
xfr.identifier = nil
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_case')
|
2
|
+
require 'catissue/defaults_test_fixture'
|
3
|
+
|
4
|
+
class UserTest < Test::Unit::TestCase
|
5
|
+
include CaTissue::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
@user = defaults.tissue_bank.coordinator
|
10
|
+
end
|
11
|
+
|
12
|
+
# # Verifies the secondary key.
|
13
|
+
# def test_secondary_key
|
14
|
+
# assert_equal(@user.login_name, @user.key, 'Key incorrect')
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# def test_defaults
|
18
|
+
# verify_defaults
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# # Exercises setting the login name from the email address.
|
22
|
+
# def test_default_login_value
|
23
|
+
# @user.login_name = nil
|
24
|
+
# verify_defaults
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# # Exercises setting the email address from the login name.
|
28
|
+
# def test_default_email_value
|
29
|
+
# @user.email_address = nil
|
30
|
+
# verify_defaults
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# def verify_defaults
|
34
|
+
# @user.address.identifier = 1
|
35
|
+
# @user.cancer_research_group.identifier = 2
|
36
|
+
# @user.department.identifier = 3
|
37
|
+
# @user.institution.identifier = 4
|
38
|
+
# super(@user)
|
39
|
+
# end
|
40
|
+
|
41
|
+
# Tests creating a user.
|
42
|
+
def test_save
|
43
|
+
addr = @user.email_address
|
44
|
+
at_ndx = addr.index('@')
|
45
|
+
modifier = "_#{Uniquifier.qualifier.to_s}"
|
46
|
+
@user.email_address = addr.insert(at_ndx, modifier)
|
47
|
+
@user.login_name = nil
|
48
|
+
verify_save(@user)
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'date'
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'test_case')
|
3
|
+
require 'catissue/extract/delta'
|
4
|
+
|
5
|
+
class DeltaTest < Test::Unit::TestCase
|
6
|
+
include CaTissue::TestCase
|
7
|
+
|
8
|
+
def test_specimen
|
9
|
+
since = DateTime.now
|
10
|
+
spc = defaults.specimen.create
|
11
|
+
ids = CaTissue::Delta.new(spc.class, since).to_a
|
12
|
+
assert(!ids.empty?, "Delta is empty")
|
13
|
+
assert_equal(1, ids.size, "Delta count incorrect")
|
14
|
+
assert_equal(spc.identifier, ids.first, "Delta value incorrect")
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_scg
|
18
|
+
since = DateTime.now
|
19
|
+
scg = defaults.specimen_collection_group.create
|
20
|
+
ids = CaTissue::Delta.new(scg.class, since).to_a
|
21
|
+
assert(!ids.empty?, "Delta is empty")
|
22
|
+
assert_equal(1, ids.size, "Delta count incorrect")
|
23
|
+
assert_equal(scg.identifier, ids.first, "Delta value incorrect")
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'test_case')
|
2
|
+
require 'catissue/extract/extractor'
|
3
|
+
|
4
|
+
class ExtractorTest < Test::Unit::TestCase
|
5
|
+
include CaTissue::TestCase
|
6
|
+
|
7
|
+
CONFIG_DIR = File.join('test', 'fixtures', 'catissue', 'extract', 'conf')
|
8
|
+
|
9
|
+
def test_specimen_write
|
10
|
+
config = File.join(CONFIG_DIR, 'spc_extract.yaml')
|
11
|
+
spc = defaults.specimen.create
|
12
|
+
extractor = CaTissue::Extractor.new(:file => config, :ids => [spc.identifier])
|
13
|
+
extractor.run
|
14
|
+
mapping = File.join(CONFIG_DIR, 'spc_fields.yaml')
|
15
|
+
mapper = CaRuby::CsvMapper.new(mapping, spc.class, extractor.output)
|
16
|
+
rec = mapper.csvio.to_a.first
|
17
|
+
assert_not_nil(rec, "Specimen record not written")
|
18
|
+
mrn = spc.path_value("specimen_collection_group.registration.participant_identifier")
|
19
|
+
assert_equal(mrn.to_s, rec[:mrn].to_s, "Specimen MRN incorrect")
|
20
|
+
spn = spc.path_value("specimen_collection_group.surgical_pathology_number")
|
21
|
+
assert_equal(spn.to_s, rec[:spn].to_s, "Specimen SPN incorrect")
|
22
|
+
date = spc.path_value("specimen_collection_group.collection_event_parameters.timestamp")
|
23
|
+
assert_equal(date.to_s, rec[:collection_date].to_s, "Specimen collection date incorrect")
|
24
|
+
assert_equal(spc.initial_quantity.to_s, rec[:quantity].to_s, "Quantity incorrect")
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_scg_write
|
28
|
+
config = File.join(CONFIG_DIR, 'scg_extract.yaml')
|
29
|
+
scg = defaults.specimen_collection_group.create
|
30
|
+
extractor = CaTissue::Extractor.new(:file => config, :ids => [scg.identifier])
|
31
|
+
extractor.run
|
32
|
+
mapping = File.join(CONFIG_DIR, 'scg_fields.yaml')
|
33
|
+
mapper = CaRuby::CsvMapper.new(mapping, scg.class, extractor.output)
|
34
|
+
rec = mapper.csvio.to_a.first
|
35
|
+
assert_not_nil(rec, "SCG record not written")
|
36
|
+
mrn = scg.path_value("registration.participant_identifier")
|
37
|
+
assert_equal(mrn.to_s, rec[:mrn].to_s, "SCG MRN incorrect")
|
38
|
+
spn = scg.path_value("surgical_pathology_number")
|
39
|
+
assert_equal(spn.to_s, rec[:spn].to_s, "SCG SPN incorrect")
|
40
|
+
date = scg.path_value("collection_event_parameters.timestamp")
|
41
|
+
assert_equal(date.to_s, rec[:collection_date].to_s, "SCG collection date incorrect")
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
$:.unshift 'lib'
|
2
|
+
$:.unshift '../caruby/lib'
|
3
|
+
|
4
|
+
require "test/unit"
|
5
|
+
|
6
|
+
require 'catissue'
|
7
|
+
|
8
|
+
class ImportableTest < Test::Unit::TestCase
|
9
|
+
LOG_FILE = 'test/results/catissue/import/log/catissue.log'
|
10
|
+
|
11
|
+
def test_import
|
12
|
+
assert_nothing_raised(Exception, 'Java class not imported') { CaTissue::CollectionProtocol }
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
LOG_FILE = 'test/results/log/migration.log'
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'test_case')
|
4
|
+
require 'caruby/domain/uniquify'
|
5
|
+
require 'catissue/migration/migrator'
|
6
|
+
|
7
|
+
module CaTissue
|
8
|
+
module MigrationTestCase
|
9
|
+
include CaTissue::TestCase
|
10
|
+
|
11
|
+
#@param [String] fixtures the fixtures directory
|
12
|
+
def setup(fixtures)
|
13
|
+
@fixtures = fixtures
|
14
|
+
# Clear the uniquifier for this migration.
|
15
|
+
CaRuby::ResourceUniquifier.instance.clear
|
16
|
+
end
|
17
|
+
|
18
|
+
## MIGRATION TEST UTILITY METHODS ##
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Runs a migrator on the given input fixture and options.
|
23
|
+
#
|
24
|
+
# @param (see #create_migrator)
|
25
|
+
# @option (see #create_migrator)
|
26
|
+
def migrate_to_database(fixture, opts={}, &verifier)
|
27
|
+
mgtr = create_migrator(fixture, opts)
|
28
|
+
logger.debug { "Migration test migrating #{fixture} fixture..." }
|
29
|
+
mgtr.migrate_to_database(&verifier)
|
30
|
+
logger.debug { "Migration test migrated #{fixture} fixture." }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Creates a new Migrator for the given fixture with the given options.
|
34
|
+
# If a factory block is provided, then that factory is called to make a new
|
35
|
+
# Migrator instance. Otherwise, {CaTissue::Migrator#initialize} makes the instance.
|
36
|
+
#
|
37
|
+
# If there is no :input option, then the migration input is set to the
|
38
|
+
# _fixture_.+csv+ file in the {#initialize} fixtures directory.
|
39
|
+
#
|
40
|
+
# @param [Symbol] fixture the migration test fixture
|
41
|
+
# @param [{Symbol => Object}] opts (see CaTissue::Migrator#initialize)
|
42
|
+
# @option (see CaTissue::Migrator#initialize)
|
43
|
+
# @return [CaTissue::Migrator]
|
44
|
+
# @yield [opts] the optional Migrator factory
|
45
|
+
def create_migrator(fixture, opts={}, &factory)
|
46
|
+
opts[:quiet] = true
|
47
|
+
opts[:input] ||= File.join(@fixtures, fixture.to_s + '.csv')
|
48
|
+
block_given? ? yield(opts) : CaTissue::Migrator.new(opts)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Verifies that the given test fixture is successfully migrated.
|
52
|
+
# Each migrated target object is validated using {CaTissue::TestCase#verify_saved}.
|
53
|
+
# In addition, if a verifier block is given to this method, then that block is
|
54
|
+
# called on the target migration object, or nil if no target was migrated.
|
55
|
+
# Supported options are described in {CaTissue::Migrator#migrate}.
|
56
|
+
#
|
57
|
+
# @param (see #verify_target)
|
58
|
+
# @option (see #verify_target)
|
59
|
+
# @yield (see #verify_target)
|
60
|
+
# @yieldparam (see #verify_target)
|
61
|
+
def verify_save(fixture, opts={})
|
62
|
+
logger.debug { "Migrating the #{fixture} test fixture..." }
|
63
|
+
opts[:unique] = true unless opts.has_key?(:unique)
|
64
|
+
opts[:controlled_values] = true unless opts.has_key?(:controlled_values)
|
65
|
+
migrate_to_database(fixture, opts) do |tgt|
|
66
|
+
verify_saved(tgt)
|
67
|
+
yield tgt if block_given?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Verifies the given fixture migration.
|
72
|
+
# Each migrated target object is validated using {#validate_target}.
|
73
|
+
# The target is migrated but not stored.
|
74
|
+
#
|
75
|
+
# @param [Symbol] fixture the test fixture to verify
|
76
|
+
# @param [<Symbol>] opts the migration options
|
77
|
+
# @option (see CaTissue::Migrator#migrate)
|
78
|
+
# @yield [target] verifies the given target
|
79
|
+
# @yieldparam [Resource] target the domain object to verify
|
80
|
+
def verify_target(fixture, opts={}, &verifier)
|
81
|
+
opts[:unique] ||= false
|
82
|
+
create_migrator(fixture, opts).migrate { |tgt| validate_target(tgt, &verifier) }
|
83
|
+
end
|
84
|
+
|
85
|
+
# Validates that the given target was successfully migrated.
|
86
|
+
# If a target was migrated, then this method calls {CaTissue::TestCase#verify_defaults}
|
87
|
+
# to confirm that the target can be stored.
|
88
|
+
# In addition, if a block is given to this method then the block is called on the
|
89
|
+
# (possibly nil) migration target.
|
90
|
+
#
|
91
|
+
# @param [Resource] target the domain object to verify
|
92
|
+
# @yield (see #verify_target)
|
93
|
+
# @yieldparam (see #verify_target)
|
94
|
+
def validate_target(target)
|
95
|
+
assert_not_nil(target, "Missing target")
|
96
|
+
logger.debug { "Validating migration target #{target}..." }
|
97
|
+
verify_defaults(target) if target
|
98
|
+
yield target if block_given?
|
99
|
+
logger.debug { "Validated migration target #{target}." }
|
100
|
+
target
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
# load the core gem
|
2
|
+
require 'rubygems'
|
3
|
+
begin
|
4
|
+
gem 'caruby-core'
|
5
|
+
rescue LoadError
|
6
|
+
# if the gem is not available, then try a local development source
|
7
|
+
$:.unshift '../caruby/lib'
|
8
|
+
end
|
9
|
+
|
10
|
+
# open the logger
|
11
|
+
LOG_FILE = 'test/results/log/catissue.log' unless defined?(LOG_FILE)
|
12
|
+
require 'caruby/util/log' and
|
13
|
+
CaRuby::Log.instance.open(LOG_FILE, :shift_age => 10, :shift_size => 1048576, :debug => true)
|
14
|
+
|
15
|
+
# Add the caruby-tissue source
|
16
|
+
$:.unshift '../catissue/lib'
|
17
|
+
|
18
|
+
require 'catissue'
|
19
|
+
require '../catissue/test/fixtures/lib/catissue/defaults_test_fixture'
|
20
|
+
|
21
|
+
module CaTissue
|
22
|
+
module TestCase
|
23
|
+
attr_reader :database
|
24
|
+
|
25
|
+
def setup
|
26
|
+
super()
|
27
|
+
logger.info("Testing #{name}...")
|
28
|
+
@database = CaTissue::Database.instance
|
29
|
+
end
|
30
|
+
|
31
|
+
def teardown
|
32
|
+
super
|
33
|
+
@database.close if @database
|
34
|
+
logger.info("Test #{name} completed.")
|
35
|
+
end
|
36
|
+
|
37
|
+
def defaults
|
38
|
+
@defaults ||= CaTissueTest.defaults.uniquify
|
39
|
+
end
|
40
|
+
|
41
|
+
# Tests the domain object +add_defaults_local+ method.
|
42
|
+
# Subclasses are responsible for setting every attribute that is a pre-condition for default value initialization.
|
43
|
+
def verify_defaults(subject)
|
44
|
+
subject.add_defaults
|
45
|
+
msg = "#{subject.qp} with default attributes fails validation"
|
46
|
+
assert_nothing_raised(ValidationError, msg) { subject.validate }
|
47
|
+
end
|
48
|
+
|
49
|
+
# Tests saving the subject. Calls {Database#save} on the subject and verifies that subject and its
|
50
|
+
# references were persisted.
|
51
|
+
#
|
52
|
+
# @param [Resource] subject the object to save
|
53
|
+
def verify_save(subject)
|
54
|
+
logger.debug{ "Verifying #{subject.qp} save with content:\n#{dump(subject)}" }
|
55
|
+
# capture the save operation time
|
56
|
+
@database.clear
|
57
|
+
st = Stopwatch.measure { @database.open { |db| db.save(subject) } }.elapsed
|
58
|
+
# the database execution time
|
59
|
+
dt = @database.execution_time
|
60
|
+
logger.debug { "#{subject.qp} save took #{'%.2f' % st} seconds, of which #{'%.2f' % dt} were database operations." }
|
61
|
+
verify_saved(subject)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Verifies that the given subject and its references were persisted.
|
65
|
+
#
|
66
|
+
# @param [Resource] subject the saved object to verify
|
67
|
+
def verify_saved(subject)
|
68
|
+
logger.debug { "Verifying saved content of #{subject}..." }
|
69
|
+
subject.dependent? ? verify_saved_dependent(subject) : verify_saved_independent(subject)
|
70
|
+
logger.debug { "Verified saved content of #{subject}." }
|
71
|
+
end
|
72
|
+
|
73
|
+
# Tests a query on the given template.
|
74
|
+
# The block given to this method is called on the query result.
|
75
|
+
def verify_query(template, *path) # :yields: result
|
76
|
+
yield database.query(template, *path)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns the Ruby date as determined by setting a Java Date property.
|
80
|
+
def date(year, month, day)
|
81
|
+
jdate = java.util.Calendar.instance
|
82
|
+
jdate.clear
|
83
|
+
jdate.set(year, month - 1, day)
|
84
|
+
jdate.time.to_ruby_date
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def dump(obj)
|
90
|
+
@database.lazy_loader.suspend { obj.dump }
|
91
|
+
end
|
92
|
+
|
93
|
+
# @param (see #mock_storable_template)
|
94
|
+
# @return (see #mock_storable_template)
|
95
|
+
def mock_create_template(obj)
|
96
|
+
mock_storable_template(obj) { |ref| ref.class.creatable_domain_attributes }
|
97
|
+
end
|
98
|
+
|
99
|
+
# @param (see #mock_storable_template)
|
100
|
+
# @return (see #mock_storable_template)
|
101
|
+
def mock_update_template(obj)
|
102
|
+
mock_storable_template(obj) { |ref| ref.class.updatable_domain_attributes }
|
103
|
+
end
|
104
|
+
|
105
|
+
# @param [Resource] obj the domain object to "save"
|
106
|
+
# @return [Resource] the template to use in the save operation
|
107
|
+
# @yield [ref] the storable attributes
|
108
|
+
# @yieldparam [Resource] ref the domain object to "save"
|
109
|
+
def mock_storable_template(obj, &selector)
|
110
|
+
# add fake identifiers to prerequisite references
|
111
|
+
obj.class.storable_prerequisite_attributes.each do |attr|
|
112
|
+
obj.send(attr).enumerate { |ref| ref.identifier = 1 }
|
113
|
+
end
|
114
|
+
# the template builder
|
115
|
+
bldr = CaRuby::StoreTemplateBuilder.new(@database, &selector)
|
116
|
+
# the save template
|
117
|
+
bldr.build_template(obj)
|
118
|
+
end
|
119
|
+
|
120
|
+
def verify_saved_dependent(dependent)
|
121
|
+
verify_dependency(dependent)
|
122
|
+
verify_saved_content(dependent)
|
123
|
+
end
|
124
|
+
|
125
|
+
def verify_dependency(dependent)
|
126
|
+
return if dependent.class.owner_attribute.nil?
|
127
|
+
owner = dependent.owner
|
128
|
+
assert_not_nil(owner, "Owner missing for dependent: #{dependent}")
|
129
|
+
attribute = owner.class.dependent_attribute(dependent.class)
|
130
|
+
assert_not_nil(attribute, "Dependent attribute missing for #{dependent} owner #{owner}")
|
131
|
+
# a dependent collection reference must be refetched
|
132
|
+
if owner.class.collection_attribute?(attribute) then
|
133
|
+
verify_saved_dependent_collection_member(dependent, owner, attribute)
|
134
|
+
else
|
135
|
+
assert_not_nil(dependent.identifier, "Stored dependent #{dependent} identifier is not set")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Verifies that the given dependent has an identifier and that the given owner dependent attribute value
|
140
|
+
# contains the dependent.
|
141
|
+
def verify_saved_dependent_collection_member(dependent, owner, attribute)
|
142
|
+
deps = owner.send(attribute)
|
143
|
+
assert(deps.include?(dependent), "Owner #{owner.qp} #{attribute} value #{deps.pp_s} does not contain #{dependent}")
|
144
|
+
assert_not_nil(dependent.identifier, "Identifier not set for stored owner #{owner.qp} #{attribute} dependent collection member #{dependent}")
|
145
|
+
end
|
146
|
+
|
147
|
+
# Verifies the subject stored content.
|
148
|
+
def verify_saved_independent(subject)
|
149
|
+
subject_id = subject.identifier
|
150
|
+
assert_not_nil(subject_id, "#{subject.class.qp} identifier not set")
|
151
|
+
verify_saved_content(subject)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Verifies that the given subject matches the database content. Does not verify subject unless it has
|
155
|
+
# a secondary key.
|
156
|
+
def verify_saved_content(subject)
|
157
|
+
attrs = subject.class.secondary_key_attributes & subject.class.mandatory_attributes
|
158
|
+
return if attrs.empty?
|
159
|
+
missing = attrs.reject { |attr| subject.send(attr) }
|
160
|
+
assert(missing.empty?, "#{subject} is missing values for secondary key attributes #{missing.to_series}")
|
161
|
+
# make a secondary key search template
|
162
|
+
vh = attrs.to_compact_hash do |attr|
|
163
|
+
v = subject.send(attr)
|
164
|
+
Resource === v ? v.copy : v
|
165
|
+
end
|
166
|
+
tmpl = subject.class.new(vh)
|
167
|
+
# find the template in the database
|
168
|
+
logger.debug { "Verifying #{subject.qp} by finding and comparing template #{tmpl.pp_s}..." }
|
169
|
+
assert_not_nil(tmpl.find, "#{subject} not found in database")
|
170
|
+
# compare the subject to the fetched template
|
171
|
+
verify_that_saved_matches_fetched(subject, tmpl)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Verifies that the given expected domain object has the same content as actual,
|
175
|
+
# and that the dependents match.
|
176
|
+
#
|
177
|
+
# @param [Resource] expected the saved value
|
178
|
+
# @param [Resource] actual the fetched value
|
179
|
+
def verify_that_saved_matches_fetched(expected, actual)
|
180
|
+
expected.class.saved_nondomain_attributes.each do |attr|
|
181
|
+
# compare attributes that are fetched and set on create
|
182
|
+
attr_md = expected.class.attribute_metadata(attr)
|
183
|
+
if verify_saved_attribute?(attr_md) then
|
184
|
+
eval = expected.database.lazy_loader.suspend { expected.send(attr) }
|
185
|
+
next if eval.nil_or_empty?
|
186
|
+
aval = actual.send(attr)
|
187
|
+
if eval.nil? then
|
188
|
+
assert_nil(aval, "#{expected.qp} was saved without a #{attr} value, but was stored in the database with value #{actual.qp}")
|
189
|
+
else
|
190
|
+
assert_not_nil(aval, "#{expected.qp} was saved with #{attr} value #{eval.qp}, but this value was not found in the database.")
|
191
|
+
assert(CaRuby::Resource.value_equal?(eval, aval), "#{expected.qp} was saved with #{attr} value #{eval.qp} that does not match the database value #{aval.qp}")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
verify_dependents_match(expected, actual)
|
196
|
+
end
|
197
|
+
|
198
|
+
# @param [AttributeMetadata] attr_md the saved attribute to check
|
199
|
+
# @return whether the attribute is fetched, creatable and not volatile
|
200
|
+
def verify_saved_attribute?(attr_md)
|
201
|
+
attr_md.fetched? and attr_md.creatable? and not attr_md.volatile?
|
202
|
+
end
|
203
|
+
|
204
|
+
# Verifies that each expected dependent matches an actual dependent and has the same content.
|
205
|
+
def verify_dependents_match(expected, actual)
|
206
|
+
expected.class.dependent_attributes.each do |attr|
|
207
|
+
edeps = expected.database.lazy_loader.suspend { expected.send(attr) }
|
208
|
+
next if edeps.nil_or_empty?
|
209
|
+
adeps = actual.send(attr)
|
210
|
+
logger.debug { "Verifying #{expected.qp} dependent #{attr} #{edeps.qp} against #{actual.qp} #{adeps.qp}..." } unless edeps.nil_or_empty?
|
211
|
+
if edeps.collection? then
|
212
|
+
edeps.each do |edep|
|
213
|
+
adep = edep.match_in_owner_scope(adeps)
|
214
|
+
assert_not_nil(adep, "#{expected} #{attr} dependent #{edep} not found in fetched #{adeps.pp_s}")
|
215
|
+
verify_that_saved_matches_fetched(edep, adep)
|
216
|
+
end
|
217
|
+
else
|
218
|
+
edep = edeps; adep = adeps;
|
219
|
+
assert_not_nil(adep, "#{expected} #{attr} dependent #{edep} not found in database")
|
220
|
+
verify_that_saved_matches_fetched(edep, adep)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|