Mining computation update

* Added various views and helper functions used by the mining
computation but which may be re-used in other parts.

* Added mining computation update type and associated update function

* New constants: game.resources.weightBase (the value used to compute
weights from mining settings) and game.resources.extraction (the
quantity extracted in a day from a full provider at difficulty 0)
This commit is contained in:
Emmanuel BENOîT 2012-01-16 12:35:20 +01:00
parent 038bba896a
commit 74b6f2ab09
20 changed files with 1139 additions and 2 deletions

View file

@ -0,0 +1,89 @@
/*
* Test the verse.get_extraction_factor() function
*/
BEGIN;
/* Drop foreign keys on resource providers, then fill the table with
* values which can be used to test some fundamental properties of
* the computation, then create a view that returns computation results.
*/
ALTER TABLE verse.resource_providers
DROP CONSTRAINT fk_resprov_planet ,
DROP CONSTRAINT fk_resprov_resource;
CREATE FUNCTION _fill_providers( )
RETURNS VOID
AS $$
DECLARE
i INT;
j INT;
BEGIN
FOR i IN 0 .. 10
LOOP
FOR j IN 0 .. 10
LOOP
INSERT INTO verse.resource_providers(
planet_id , resource_name_id ,
resprov_quantity_max , resprov_quantity ,
resprov_difficulty , resprov_recovery
) VALUES (
i , j , 100 , j * 10 , i * 0.1 , 0.5
);
END LOOP;
END LOOP;
END;
$$ LANGUAGE PLPGSQL;
SELECT _fill_providers( );
DROP FUNCTION _fill_providers( );
CREATE VIEW extraction_factor_view
AS SELECT planet_id , resource_name_id ,
verse.get_extraction_factor(
resprov_quantity / resprov_quantity_max ,
resprov_difficulty
) AS resprov_extraction
FROM verse.resource_providers;
/***** TESTS BEGIN HERE *****/
SELECT plan( 6 );
SELECT diag_test_name( 'verse.get_extraction_factor() - Range');
SELECT is_empty($$
SELECT * FROM extraction_factor_view
WHERE resprov_extraction NOT BETWEEN 0 AND 1
$$);
SELECT diag_test_name( 'verse.get_extraction_factor() - Full provider with difficulty 0 => extraction is 1');
SELECT is( resprov_extraction , 1.0::DOUBLE PRECISION )
FROM extraction_factor_view
WHERE planet_id = 0 AND resource_name_id = 10;
SELECT diag_test_name( 'verse.get_extraction_factor() - Full provider with difficulty 1 => extraction is 0.5');
SELECT is( resprov_extraction , 0.5::DOUBLE PRECISION )
FROM extraction_factor_view
WHERE planet_id = 10 AND resource_name_id = 10;
SELECT diag_test_name( 'verse.get_extraction_factor() - Empty provider => extraction is 0');
SELECT is_empty($$
SELECT * FROM extraction_factor_view
WHERE resource_name_id = 0 AND resprov_extraction > 0
$$);
SELECT diag_test_name( 'verse.get_extraction_factor() - At same quantity ratio, higher difficulty => lower extraction');
SELECT is_empty($$
SELECT * FROM extraction_factor_view v1
INNER JOIN extraction_factor_view v2
ON v1.resource_name_id = v2.resource_name_id
WHERE v1.planet_id > v2.planet_id
AND v1.resprov_extraction > v2.resprov_extraction
$$);
SELECT diag_test_name( 'verse.get_extraction_factor() - At same difficulty, higher quantity ratio => higher extraction');
SELECT is_empty($$
SELECT * FROM extraction_factor_view v1
INNER JOIN extraction_factor_view v2
ON v1.planet_id = v2.planet_id
WHERE v1.resource_name_id > v2.resource_name_id
AND v1.resprov_extraction < v2.resprov_extraction
$$);
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,44 @@
/*
* Test sys.gu_pmc_weights_view
*/
BEGIN;
/* Create a table which will server as an alternate source for
* emp.mining_settings_view ; the table is not temporary (PostgreSQL
* won't allow replacing the view otherwise), but will be dropped
* on rollback anyway.
*/
CREATE TABLE fake_mining_settings(
planet_id INT ,
resource_name_id INT ,
mset_weight INT ,
mset_specific BOOLEAN
);
CREATE OR REPLACE VIEW emp.mining_settings_view
AS SELECT * FROM fake_mining_settings;
/* Insert fake records for each possible mining setting */
INSERT INTO fake_mining_settings VALUES
( 1 , 0 , 0 , FALSE ) ,
( 1 , 1 , 1 , FALSE ) ,
( 1 , 2 , 2 , FALSE ) ,
( 1 , 3 , 3 , FALSE ) ,
( 1 , 4 , 4 , FALSE );
/***** TESTS BEGIN HERE *****/
SELECT plan( 2 );
SELECT diag_test_name( 'sys.gu_pmc_weights_view - Rows present' );
SELECT isnt( COUNT(*)::INT , 0 )
FROM sys.gu_pmc_weights_view;
SELECT diag_test_name( 'sys.gu_pmc_weights_view - weight = game.resources.weightBase ^ setting' );
SELECT sys.uoc_constant( 'game.resources.weightBase' , '(test)' , 'Resources' , 10.0 );
SELECT is_empty( $$
SELECT * FROM sys.gu_pmc_weights_view
WHERE pmc_weight IS NULL
OR pmc_weight <> POW( 10 , resource_name_id )
$$ );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,35 @@
/*
* Test sys.gu_pmc_totals_view
*/
BEGIN;
/* Create a table which will server as an alternate source for
* sys.gu_pmc_weights_view ; the table is not temporary (PostgreSQL
* won't allow replacing the view otherwise), but will be dropped
* on rollback anyway.
*/
CREATE TABLE fake_mining_weights(
planet_id INT ,
resource_name_id INT ,
pmc_weight DOUBLE PRECISION
);
CREATE OR REPLACE VIEW sys.gu_pmc_weights_view
AS SELECT * FROM fake_mining_weights;
/* Insert fake records for two different planets */
INSERT INTO fake_mining_weights VALUES
( 1 , 0 , 1 ) ,
( 1 , 1 , 2 ) ,
( 2 , 0 , 4 ) ,
( 2 , 1 , 5 );
/***** TESTS BEGIN HERE *****/
SELECT plan( 1 );
SELECT set_eq(
$$ SELECT * FROM sys.gu_pmc_totals_view $$ ,
$$ VALUES ( 1 , 3.0 ) , ( 2 , 9.0 ) $$
);
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,89 @@
/*
* Test the sys.gu_pmc_get_data() function
*/
BEGIN;
\i utils/common-setup/setup-gu-pmc-get-data-test.sql
/* Select results into a temporary table */
CREATE TEMPORARY TABLE test_results
AS SELECT * FROM sys.gu_pmc_get_data( 0 );
/***** TESTS BEGIN HERE *****/
SELECT no_plan( );
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Neutral planet without resource providers not included' );
SELECT is_empty( $$
SELECT * FROM test_results
WHERE planet = _get_map_name ( 'planet1' );
$$ );
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Neutral planet with resource providers - Rows included' );
SELECT is( COUNT(*)::INT , 2)
FROM test_results
WHERE planet = _get_map_name ( 'planet2' )
AND difficulty = 0.2 AND empire IS NULL
AND happiness IS NULL AND weight IS NULL
AND total_weight IS NULL;
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Neutral planet with resource providers - No extra rows' );
SELECT is_empty( $$
SELECT * FROM test_results
WHERE planet = _get_map_name ( 'planet2' )
AND NOT ( difficulty = 0.2 AND empire IS NULL
AND happiness IS NULL AND weight IS NULL
AND total_weight IS NULL );
$$ );
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet using empire settings - Rows included' );
SELECT is( COUNT(*)::INT , 2)
FROM test_results
WHERE planet = _get_map_name ( 'planet3' ) AND difficulty = 0.3
AND empire = _get_emp_name( 'empire1' )
AND happiness IS NOT NULL AND weight = 100
AND total_weight = 200;
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet using empire settings - No extra rows' );
SELECT is_empty( $$
SELECT * FROM test_results
WHERE planet = _get_map_name ( 'planet3' )
AND NOT ( difficulty = 0.3
AND empire = _get_emp_name( 'empire1' )
AND happiness IS NOT NULL
AND weight = 100 AND total_weight = 200 );
$$ );
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet using specific settings - Rows included' );
SELECT is( COUNT(*)::INT , 2)
FROM test_results
WHERE planet = _get_map_name ( 'planet4' ) AND difficulty = 0.4
AND empire = _get_emp_name( 'empire2' )
AND happiness IS NOT NULL AND (
( resource = _get_string( 'resource1' ) AND weight = 10 )
OR ( resource = _get_string( 'resource2' ) AND weight = 1000 ) )
AND total_weight = 1010;
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet using specific settings - No extra rows' );
SELECT is_empty( $$
SELECT * FROM test_results
WHERE planet = _get_map_name ( 'planet4' )
AND NOT ( difficulty = 0.4
AND empire = _get_emp_name( 'empire2' )
AND happiness IS NOT NULL
AND total_weight = 1010 AND (
( resource = _get_string( 'resource1' ) AND weight = 10 )
OR ( resource = _get_string( 'resource2' ) AND weight = 1000 ) ) );
$$ );
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Owned planet without resource providers not included' );
SELECT is_empty( $$
SELECT * FROM test_results
WHERE planet = _get_map_name ( 'planet5' );
$$ );
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet matching all criterias but marked as processed not included' );
SELECT is_empty( $$
SELECT * FROM test_results
WHERE planet = _get_map_name ( 'planet6' );
$$ );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,91 @@
/*
* Test the sys.gu_pmc_update_resource() function
*/
BEGIN;
/*
* We need to create a set of both resource providers and planet resource
* records that will be updated by the function when it is called. We
* disable foreign keys on both tables, as it makes things simpler. We
* also replace verse.get_raw_production(), verse.get_extraction_factor( )
* and verse.adjust_production() so that they return fixed values, and we
* need to set the game.resources.extraction constant.
*/
ALTER TABLE verse.resource_providers
DROP CONSTRAINT fk_resprov_planet ,
DROP CONSTRAINT fk_resprov_resource;
ALTER TABLE verse.planet_resources
DROP CONSTRAINT fk_pres_planet ,
DROP CONSTRAINT fk_pres_resource;
INSERT INTO verse.resource_providers(
planet_id , resource_name_id , resprov_quantity_max, resprov_quantity ,
resprov_difficulty , resprov_recovery
) VALUES (
1 , 1 , 1000 , 1000 , 0 , 0.5
);
INSERT INTO verse.planet_resources(
planet_id , resource_name_id , pres_income , pres_upkeep
) VALUES (
1 , 1 , 0 , 0
);
CREATE OR REPLACE FUNCTION verse.get_raw_production( pid INT , pt building_output_type )
RETURNS REAL
AS $$
SELECT 1.0::REAL;
$$ LANGUAGE SQL;
CREATE OR REPLACE FUNCTION verse.adjust_production( prod REAL , happiness REAL )
RETURNS REAL
AS $$
SELECT 1.0::REAL;
$$ LANGUAGE SQL;
CREATE OR REPLACE FUNCTION verse.get_extraction_factor( _fill_ratio DOUBLE PRECISION , _difficulty DOUBLE PRECISION )
RETURNS DOUBLE PRECISION
AS $$
SELECT ( CASE WHEN $1 = 1.0 AND $2 = 0 THEN 0.002 ELSE 0.0 END )::DOUBLE PRECISION;
$$ LANGUAGE SQL;
SELECT sys.uoc_constant( 'game.resources.extraction' , '(test)' , 'Resources' , 1440.0 );
ALTER FUNCTION sys.get_constant( TEXT ) VOLATILE;
/***** TESTS BEGIN HERE *****/
SELECT plan( 4 );
SELECT sys.gu_pmc_update_resource( ROW(
1 , 1 , 1000.0 , 1000.0 , 0.0 , NULL , 1.0 , 0.5 , 1.0
) );
SELECT diag_test_name( 'sys.gu_pmc_update_resource( ) - Provider udpated' );
SELECT is( resprov_quantity , 999.0::DOUBLE PRECISION )
FROM verse.resource_providers
WHERE planet_id = 1 AND resource_name_id = 1;
SELECT diag_test_name( 'sys.gu_pmc_update_resource( ) - Planet resources income udpated' );
SELECT is( pres_income , 1.0::DOUBLE PRECISION )
FROM verse.planet_resources
WHERE planet_id = 1 AND resource_name_id = 1;
UPDATE verse.resource_providers SET resprov_quantity = resprov_quantity_max;
UPDATE sys.constant_definitions
SET c_value = 14400000.0
WHERE name = 'game.resources.extraction';
SELECT sys.gu_pmc_update_resource( ROW(
1 , 1 , 1000.0 , 1000.0 , 0.0 , NULL , 1.0 , 0.5 , 1.0
) );
SELECT diag_test_name( 'sys.gu_pmc_update_resource( ) - Bounded extraction quantity (1/2)' );
SELECT is( resprov_quantity , 0.0::DOUBLE PRECISION )
FROM verse.resource_providers
WHERE planet_id = 1 AND resource_name_id = 1;
SELECT diag_test_name( 'sys.gu_pmc_update_resource( ) - Bounded extraction quantity (2/2)' );
SELECT is( pres_income , 1000.0::DOUBLE PRECISION )
FROM verse.planet_resources
WHERE planet_id = 1 AND resource_name_id = 1;
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,58 @@
/*
* Test the sys.process_planet_mining_updates() function
*/
BEGIN;
/*
* Create a fake planet resource record which will be updated by the
* function (dropping the foreign key is therefore needed).
*/
ALTER TABLE verse.planet_resources
DROP CONSTRAINT fk_pres_planet ,
DROP CONSTRAINT fk_pres_resource;
INSERT INTO verse.planet_resources(
planet_id , resource_name_id , pres_income , pres_upkeep
) VALUES (
1 , 1 , 42 , 0
);
/*
* Create a table which contains the values which will be returned by
* the fake sys.gu_pmc_get_data( ).
*/
CREATE TABLE _fake_update_data OF sys.gu_pmc_data_type;
INSERT INTO _fake_update_data VALUES (
1 , 1 , 1000.0 , 1000.0 , 0.5 , NULL , NULL , NULL , NULL ) ,
( 2 , 1 , 1000.0 , 1000.0 , 0.5 , 1 , 0.5 , 1.0 , 1.0 );
CREATE OR REPLACE FUNCTION sys.gu_pmc_get_data( _tick BIGINT )
RETURNS SETOF sys.gu_pmc_data_type
AS $$
SELECT * FROM _fake_update_data;
$$ LANGUAGE SQL;
/*
* Replace sys.gu_pmc_update_resource() so it deletes records from the
* table.
*/
CREATE OR REPLACE FUNCTION sys.gu_pmc_update_resource( _input sys.gu_pmc_data_type )
RETURNS VOID
AS $$
DELETE FROM _fake_update_data WHERE planet = $1.planet AND resource = $1.resource;
$$ LANGUAGE SQL;
/***** TESTS BEGIN HERE *****/
SELECT no_plan( );
SELECT sys.process_planet_mining_updates( 0 );
SELECT diag_test_name( 'sys.process_planet_mining_updates() - Neutral planets updated' );
SELECT is( pres_income , 0::DOUBLE PRECISION ) FROM verse.planet_resources;
SELECT diag_test_name( 'sys.process_planet_mining_updates() - Owned planets updated' );
SELECT is_empty(
$$ SELECT * FROM _fake_update_data WHERE planet = 2 $$
);
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,8 @@
/*
* Prepare for the locking tests on sys.gu_pmc_get_data()
*/
BEGIN;
CREATE EXTENSION pageinspect;
\i utils/common-setup/setup-gu-pmc-get-data-test.sql
\i utils/locks-finder.sql
COMMIT;

View file

@ -0,0 +1,104 @@
/*
* Test the locks set by sys.gu_pmc_get_data( )
*/
BEGIN;
SELECT * FROM sys.gu_pmc_get_data( 0 );
SELECT plan( 7 );
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on planets' );
SELECT set_eq ( $$
SELECT name_id , shared , exclusive
FROM verse.planets pl
INNER JOIN ( SELECT * FROM _get_locks_on( 'verse.planets' ) ) p
ON p.ctid = pl.ctid;
$$ , $$
VALUES ( _get_map_name( 'planet2' ) , TRUE , FALSE ) ,
( _get_map_name( 'planet3' ) , TRUE , FALSE ) ,
( _get_map_name( 'planet4' ) , TRUE , FALSE );
$$
);
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on resource providers' );
SELECT set_eq ( $$
SELECT planet_id , resource_name_id , shared , exclusive
FROM verse.resource_providers rp
INNER JOIN ( SELECT * FROM _get_locks_on( 'verse.resource_providers' ) ) p
ON p.ctid = rp.ctid;
$$ , $$
VALUES ( _get_map_name( 'planet2' ) , _get_string('resource1') , FALSE , TRUE ) ,
( _get_map_name( 'planet2' ) , _get_string('resource2') , FALSE , TRUE ) ,
( _get_map_name( 'planet3' ) , _get_string('resource1') , FALSE , TRUE ) ,
( _get_map_name( 'planet3' ) , _get_string('resource2') , FALSE , TRUE ) ,
( _get_map_name( 'planet4' ) , _get_string('resource1') , FALSE , TRUE ) ,
( _get_map_name( 'planet4' ) , _get_string('resource2') , FALSE , TRUE );
$$
);
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on planet resources' );
SELECT set_eq ( $$
SELECT planet_id , resource_name_id , shared , exclusive
FROM verse.planet_resources pr
INNER JOIN ( SELECT * FROM _get_locks_on( 'verse.planet_resources' ) ) p
ON p.ctid = pr.ctid;
$$ , $$
VALUES ( _get_map_name( 'planet2' ) , _get_string('resource1') , FALSE , TRUE ) ,
( _get_map_name( 'planet2' ) , _get_string('resource2') , FALSE , TRUE ) ,
( _get_map_name( 'planet3' ) , _get_string('resource1') , FALSE , TRUE ) ,
( _get_map_name( 'planet3' ) , _get_string('resource2') , FALSE , TRUE ) ,
( _get_map_name( 'planet4' ) , _get_string('resource1') , FALSE , TRUE ) ,
( _get_map_name( 'planet4' ) , _get_string('resource2') , FALSE , TRUE );
$$
);
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on empire planets' );
SELECT set_eq ( $$
SELECT planet_id , empire_id , shared , exclusive
FROM emp.planets ep
INNER JOIN ( SELECT * FROM _get_locks_on( 'emp.planets' ) ) p
ON p.ctid = ep.ctid;
$$ , $$
VALUES ( _get_map_name( 'planet3' ) , _get_emp_name('empire1' ) , TRUE , FALSE ) ,
( _get_map_name( 'planet4' ) , _get_emp_name('empire2' ) , TRUE , FALSE );
$$
);
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on mining settings' );
SELECT set_eq ( $$
SELECT empire_id , resource_name_id , shared , exclusive
FROM emp.mining_settings ms
INNER JOIN ( SELECT * FROM _get_locks_on( 'emp.mining_settings' ) ) p
ON p.ctid = ms.ctid;
$$ , $$
VALUES ( _get_emp_name('empire1' ) , _get_string( 'resource1' ) , TRUE , FALSE ) ,
( _get_emp_name('empire1' ) , _get_string( 'resource2' ) , TRUE , FALSE ) ,
( _get_emp_name('empire2' ) , _get_string( 'resource1' ) , TRUE , FALSE ) ,
( _get_emp_name('empire2' ) , _get_string( 'resource2' ) , TRUE , FALSE );
$$
);
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on planet mining settings' );
SELECT set_eq ( $$
SELECT empire_id , planet_id , resource_name_id , shared , exclusive
FROM emp.planet_mining_settings ms
INNER JOIN ( SELECT * FROM _get_locks_on( 'emp.planet_mining_settings' ) ) p
ON p.ctid = ms.ctid;
$$ , $$
VALUES ( _get_emp_name('empire2' ) , _get_map_name( 'planet4' ) , _get_string( 'resource1' ) , TRUE , FALSE ) ,
( _get_emp_name('empire2' ) , _get_map_name( 'planet4' ) , _get_string( 'resource2' ) , TRUE , FALSE );
$$
);
SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on planet happiness records' );
SELECT set_eq ( $$
SELECT planet_id , shared , exclusive
FROM verse.planet_happiness pl
INNER JOIN ( SELECT * FROM _get_locks_on( 'verse.planet_happiness' ) ) p
ON p.ctid = pl.ctid;
$$ , $$
VALUES ( _get_map_name( 'planet3' ) , TRUE , FALSE ) ,
( _get_map_name( 'planet4' ) , TRUE , FALSE );
$$
);
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,13 @@
/*
* Test privileges on verse.get_extraction_factor()
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'verse.get_extraction_factor() - Privileges' );
SELECT throws_ok( $$
SELECT verse.get_extraction_factor( 0.5 , 0.5 )
$$ , 42501 );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,11 @@
/*
* Test privileges on sys.gu_pmc_weights_view
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'sys.gu_pmc_weights_view - Privileges' );
SELECT throws_ok( 'SELECT * FROM sys.gu_pmc_weights_view' , 42501 );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,11 @@
/*
* Test privileges on sys.gu_pmc_totals_view
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'sys.gu_pmc_totals_view - Privileges' );
SELECT throws_ok( 'SELECT * FROM sys.gu_pmc_totals_view' , 42501 );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,11 @@
/*
* Test privileges on sys.gu_pmc_get_data( )
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'sys.gu_pmc_get_data - Privileges' );
SELECT throws_ok( 'SELECT * FROM sys.gu_pmc_get_data( 0 )' , 42501 );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,13 @@
/*
* Test privileges on sys.gu_pmc_update_resource( )
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'sys.gu_pmc_update_resource - Privileges' );
SELECT throws_ok( $$
SELECT * FROM sys.gu_pmc_update_resource( ROW( NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL , NULL ) );
$$ , 42501 );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,11 @@
/*
* Test privileges on sys.process_planet_mining_updates( )
*/
BEGIN;
SELECT plan( 1 );
SELECT diag_test_name( 'sys.process_planet_mining_updates() - Privileges' );
SELECT throws_ok( 'SELECT * FROM sys.process_planet_mining_updates( 0 )' , 42501 );
SELECT * FROM finish( );
ROLLBACK;

View file

@ -0,0 +1,170 @@
/*
* We need rows in quite a few tables to make sure locking works as
* advertised.
*
* - First we will need a planet with no resource providers. This one
* shouldn't be selected at all.
*
* - We need a planet with resource providers, but no owning empire. The
* planet will be selected, but all fields that are obtained from the
* empire's data will be NULL.
*
* - We need a planet owned by an empire for which empire-wide settings
* will be used.
*
* - We need a planet owned by an empire but that uses planet-specific
* settings.
*
* - We need a planet with no resource providers owned by an empire. This
* one shouldn't be selected.
*
* - Finally, we need a planet that matches the criterias but isn't
* scheduled for an update at the time.
*
* FIXME: for now, locking is NOT tested. I simply have no idea how to do
* it, at least not without creating an extra database and that
* kind of stuff.
*
* FIXME: cannot test where the happiness column comes from until values
* all use DOUBLE PRECISION.
*/
\i utils/strings.sql
\i utils/resources.sql
\i utils/accounts.sql
\i utils/naming.sql
\i utils/universe.sql
SELECT sys.uoc_constant( 'game.resources.weightBase' , '(test)' , 'Resources' , 10.0 );
SELECT _create_natural_resources( 2 , 'resource' );
SELECT _create_raw_planets( 6 , 'planet' );
SELECT _create_emp_names( 4 , 'empire' );
INSERT INTO emp.empires ( name_id , cash )
SELECT id , 0 FROM naming.empire_names;
/* Planet #1 */
INSERT INTO sys.updates( id , gu_type , status , last_tick )
VALUES ( 1 , 'PLANET_MINING' , 'PROCESSING' , 0 );
INSERT INTO verse.updates( update_id , planet_id )
VALUES ( 1 , _get_map_name( 'planet1' ) );
/* Planet #2 */
INSERT INTO sys.updates( id , gu_type , status , last_tick )
VALUES ( 2 , 'PLANET_MINING' , 'PROCESSING' , 0 );
INSERT INTO verse.updates( update_id , planet_id )
VALUES ( 2 , _get_map_name( 'planet2' ) );
INSERT INTO verse.resource_providers (
planet_id , resource_name_id , resprov_quantity_max ,
resprov_quantity , resprov_difficulty , resprov_recovery
) VALUES (
_get_map_name( 'planet2' ) , _get_string( 'resource1' ) , 100 ,
100 , 0.2 , 0.5
) , (
_get_map_name( 'planet2' ) , _get_string( 'resource2' ) , 100 ,
100 , 0.2 , 0.5
);
/* Planet #3 */
INSERT INTO sys.updates( id , gu_type , status , last_tick )
VALUES ( 3 , 'PLANET_MINING' , 'PROCESSING' , 0 );
INSERT INTO verse.updates( update_id , planet_id )
VALUES ( 3 , _get_map_name( 'planet3' ) );
INSERT INTO verse.resource_providers (
planet_id , resource_name_id , resprov_quantity_max ,
resprov_quantity , resprov_difficulty , resprov_recovery
) VALUES (
_get_map_name( 'planet3' ) , _get_string( 'resource1' ) , 100 ,
100 , 0.3 , 0.5
) , (
_get_map_name( 'planet3' ) , _get_string( 'resource2' ) , 100 ,
100 , 0.3 , 0.5
);
INSERT INTO verse.planet_happiness ( planet_id , current , target )
VALUES ( _get_map_name( 'planet3' ) , 0.3 , 0.3 );
INSERT INTO emp.planets ( empire_id , planet_id )
VALUES ( _get_emp_name( 'empire1' ) , _get_map_name( 'planet3' ) );
INSERT INTO emp.mining_settings( empire_id , resource_name_id , empmset_weight )
VALUES (
_get_emp_name( 'empire1' ) , _get_string( 'resource1' ) , 2
) , (
_get_emp_name( 'empire1' ) , _get_string( 'resource2' ) , 2
);
/* Planet #4 */
INSERT INTO sys.updates( id , gu_type , status , last_tick )
VALUES ( 4 , 'PLANET_MINING' , 'PROCESSING' , 0 );
INSERT INTO verse.updates( update_id , planet_id )
VALUES ( 4 , _get_map_name( 'planet4' ) );
INSERT INTO verse.resource_providers (
planet_id , resource_name_id , resprov_quantity_max ,
resprov_quantity , resprov_difficulty , resprov_recovery
) VALUES (
_get_map_name( 'planet4' ) , _get_string( 'resource1' ) , 100 ,
100 , 0.4 , 0.5
) , (
_get_map_name( 'planet4' ) , _get_string( 'resource2' ) , 100 ,
100 , 0.4 , 0.5
);
INSERT INTO verse.planet_happiness ( planet_id , current , target )
VALUES ( _get_map_name( 'planet4' ) , 0.4 , 0.4 );
INSERT INTO emp.planets ( empire_id , planet_id )
VALUES ( _get_emp_name( 'empire2' ) , _get_map_name( 'planet4' ) );
INSERT INTO emp.mining_settings( empire_id , resource_name_id , empmset_weight )
VALUES (
_get_emp_name( 'empire2' ) , _get_string( 'resource1' ) , 2
) , (
_get_emp_name( 'empire2' ) , _get_string( 'resource2' ) , 2
);
INSERT INTO emp.planet_mining_settings(
empire_id , planet_id , resource_name_id , emppmset_weight
) VALUES (
_get_emp_name( 'empire2' ) , _get_map_name( 'planet4' ) , _get_string( 'resource1' ) , 1
) , (
_get_emp_name( 'empire2' ) , _get_map_name( 'planet4' ) , _get_string( 'resource2' ) , 3
);
/* Planet #5 */
INSERT INTO sys.updates( id , gu_type , status , last_tick )
VALUES ( 5 , 'PLANET_MINING' , 'PROCESSING' , 0 );
INSERT INTO verse.updates( update_id , planet_id )
VALUES ( 5 , _get_map_name( 'planet5' ) );
INSERT INTO verse.planet_happiness ( planet_id , current , target )
VALUES ( _get_map_name( 'planet5' ) , 0.5 , 0.5 );
INSERT INTO emp.planets ( empire_id , planet_id )
VALUES ( _get_emp_name( 'empire3' ) , _get_map_name( 'planet5' ) );
INSERT INTO emp.mining_settings( empire_id , resource_name_id , empmset_weight )
VALUES (
_get_emp_name( 'empire3' ) , _get_string( 'resource1' ) , 2
) , (
_get_emp_name( 'empire3' ) , _get_string( 'resource2' ) , 2
);
/* Planet #6 */
INSERT INTO sys.updates( id , gu_type , status , last_tick )
VALUES ( 6 , 'PLANET_MINING' , 'PROCESSED' , 0 );
INSERT INTO verse.updates( update_id , planet_id )
VALUES ( 6 , _get_map_name( 'planet6' ) );
INSERT INTO verse.resource_providers (
planet_id , resource_name_id , resprov_quantity_max ,
resprov_quantity , resprov_difficulty , resprov_recovery
) VALUES (
_get_map_name( 'planet6' ) , _get_string( 'resource1' ) , 100 ,
100 , 0.6 , 0.5
) , (
_get_map_name( 'planet6' ) , _get_string( 'resource2' ) , 100 ,
100 , 0.6 , 0.5
);
INSERT INTO verse.planet_happiness ( planet_id , current , target )
VALUES ( _get_map_name( 'planet6' ) , 0.6 , 0.6 );
INSERT INTO emp.planets ( empire_id , planet_id )
VALUES ( _get_emp_name( 'empire4' ) , _get_map_name( 'planet6' ) );
INSERT INTO emp.mining_settings( empire_id , resource_name_id , empmset_weight )
VALUES (
_get_emp_name( 'empire4' ) , _get_string( 'resource1' ) , 2
) , (
_get_emp_name( 'empire4' ) , _get_string( 'resource2' ) , 2
);
/* Insert planet resource records */
INSERT INTO verse.planet_resources ( planet_id , resource_name_id , pres_income , pres_upkeep )
SELECT p.name_id , r.resource_name_id , 42 , 0
FROM verse.planets p CROSS JOIN defs.resources r;

View file

@ -0,0 +1,43 @@
/*
* Utility functions used by unit tests
*
* Row lock checks
*/
CREATE TYPE _locks_entry AS (
ctid tid ,
shared BOOLEAN ,
exclusive BOOLEAN
);
CREATE OR REPLACE FUNCTION _get_locks_on(
IN _table TEXT )
RETURNS SETOF _locks_entry
STRICT VOLATILE
AS $$
DECLARE
_page INT;
_pages INT;
_record RECORD;
_return _locks_entry;
BEGIN
SELECT INTO _pages pg_relation_size( _table ) / 8192;
FOR _page IN 0 .. ( _pages - 1 )
LOOP
FOR _record IN SELECT t_ctid , t_infomask
FROM heap_page_items( get_raw_page( _table , _page ) )
WHERE t_xmax::text::int > ( txid_current( ) & x'ffffffff'::bigint )
LOOP
_return := ROW( _record.t_ctid ,
_record.t_infomask & x'80'::int <> 0 ,
_record.t_infomask & x'40'::int <> 0 );
RETURN NEXT _return;
END LOOP;
END LOOP;
END;
$$ LANGUAGE PLPGSQL;