|
| 1 | + |
| 2 | +import pytest |
| 3 | +from rhosocial.activerecord.backend.impl.postgres.config import PostgresConnectionConfig |
| 4 | + |
| 5 | +def test_pg_config_to_dict(): |
| 6 | + """Test that postgres-specific parameters are added to the dictionary.""" |
| 7 | + config = PostgresConnectionConfig( |
| 8 | + database="test_db", |
| 9 | + sslmode="require", |
| 10 | + application_name="my_app" |
| 11 | + ) |
| 12 | + |
| 13 | + config_dict = config.to_dict() |
| 14 | + |
| 15 | + # Test that the pg-specific parameters are present |
| 16 | + assert config_dict['sslmode'] == 'require' |
| 17 | + assert config_dict['application_name'] == 'my_app' |
| 18 | + |
| 19 | + # Test that parameters with default value None are not present |
| 20 | + assert 'sslcert' not in config_dict |
| 21 | + |
| 22 | +def test_pg_config_to_connection_string_with_params(): |
| 23 | + """Test connection string builds correctly with various pg parameters.""" |
| 24 | + config = PostgresConnectionConfig( |
| 25 | + host="localhost", |
| 26 | + port=5432, |
| 27 | + database="test_db", |
| 28 | + username="user", |
| 29 | + sslmode="verify-full", |
| 30 | + application_name="my_app", |
| 31 | + connect_timeout=20, |
| 32 | + options={'custom_opt': 'custom_val'} |
| 33 | + ) |
| 34 | + |
| 35 | + conn_str = config.to_connection_string() |
| 36 | + base_url, params_str = conn_str.split('?') |
| 37 | + params = dict(p.split('=') for p in params_str.split('&')) |
| 38 | + |
| 39 | + assert base_url == "postgres://user@localhost:5432/test_db" # Password is None, so it's omitted |
| 40 | + assert params['sslmode'] == 'verify-full' |
| 41 | + assert params['application_name'] == 'my_app' |
| 42 | + assert params['connect_timeout'] == '20' |
| 43 | + assert params['custom_opt'] == 'custom_val' |
| 44 | + |
| 45 | +def test_pg_config_to_connection_string_no_auth(): |
| 46 | + """Test connection string with no username or password.""" |
| 47 | + config = PostgresConnectionConfig(host="localhost", port=5432, database="test_db") |
| 48 | + assert config.to_connection_string() == "postgres://localhost:5432/test_db" |
| 49 | + |
| 50 | +def test_validation_missing_host(): |
| 51 | + """Test validation fails if host is missing.""" |
| 52 | + config = PostgresConnectionConfig(database="test_db", host=None) |
| 53 | + with pytest.raises(ValueError, match="Host is required"): |
| 54 | + config.validate() |
| 55 | + |
| 56 | +def test_validation_missing_database(): |
| 57 | + """Test validation fails if database is missing.""" |
| 58 | + config = PostgresConnectionConfig(host="localhost", database=None) |
| 59 | + with pytest.raises(ValueError, match="Database name is required"): |
| 60 | + config.validate() |
| 61 | + |
| 62 | +@pytest.mark.parametrize("invalid_port", [0, -1, 65536]) |
| 63 | +def test_validation_invalid_port(invalid_port): |
| 64 | + """Test validation fails for invalid port numbers.""" |
| 65 | + config = PostgresConnectionConfig(host="localhost", database="test_db", port=invalid_port) |
| 66 | + with pytest.raises(ValueError, match=f"Invalid port number: {invalid_port}"): |
| 67 | + config.validate() |
| 68 | + |
| 69 | +def test_validation_invalid_sslmode(): |
| 70 | + """Test validation fails for an invalid sslmode.""" |
| 71 | + config = PostgresConnectionConfig(host="localhost", database="test_db", sslmode="invalid_mode") |
| 72 | + with pytest.raises(ValueError, match="Invalid sslmode"): |
| 73 | + config.validate() |
| 74 | + |
| 75 | +def test_validation_invalid_session_attrs(): |
| 76 | + """Test validation fails for invalid target_session_attrs.""" |
| 77 | + config = PostgresConnectionConfig( |
| 78 | + host="localhost", |
| 79 | + database="test_db", |
| 80 | + target_session_attrs="invalid_attr", |
| 81 | + ) |
| 82 | + with pytest.raises(ValueError, match="Invalid target_session_attrs"): |
| 83 | + config.validate() |
| 84 | + |
| 85 | +@pytest.mark.parametrize("valid_session_attr", ["any", "primary", "standby", "prefer-standby", "read-write", "read-only"]) |
| 86 | +def test_validation_valid_session_attrs(valid_session_attr): |
| 87 | + """Test validation succeeds for valid target_session_attrs.""" |
| 88 | + config = PostgresConnectionConfig( |
| 89 | + host="localhost", |
| 90 | + database="test_db", |
| 91 | + target_session_attrs=valid_session_attr, |
| 92 | + ) |
| 93 | + assert config.validate() is True |
| 94 | + |
| 95 | +def test_validation_success(): |
| 96 | + """Test a valid configuration passes validation.""" |
| 97 | + config = PostgresConnectionConfig( |
| 98 | + host="localhost", |
| 99 | + database="test_db", |
| 100 | + port=5432, |
| 101 | + sslmode="require" |
| 102 | + ) |
| 103 | + assert config.validate() is True |
| 104 | + |
| 105 | +def test_get_pool_config_defaults(): |
| 106 | + """Test getting pool config with default values.""" |
| 107 | + config = PostgresConnectionConfig(host="localhost", database="test_db") |
| 108 | + pool_config = config.get_pool_config() |
| 109 | + assert pool_config == { |
| 110 | + "min_size": 1, |
| 111 | + "max_size": 10, |
| 112 | + "timeout": 30.0, |
| 113 | + } |
| 114 | + |
| 115 | +def test_get_pool_config_custom(): |
| 116 | + """Test getting pool config with custom values from the mixin.""" |
| 117 | + config = PostgresConnectionConfig( |
| 118 | + host="localhost", |
| 119 | + database="test_db", |
| 120 | + pool_min_size=5, |
| 121 | + pool_max_size=20, |
| 122 | + pool_timeout=60.5, |
| 123 | + ) |
| 124 | + pool_config = config.get_pool_config() |
| 125 | + assert pool_config == { |
| 126 | + "min_size": 5, |
| 127 | + "max_size": 20, |
| 128 | + "timeout": 60.5, |
| 129 | + } |
| 130 | + |
| 131 | +def test_connection_string_password_behavior(): |
| 132 | + """Test that connection string correctly handles password.""" |
| 133 | + # With password |
| 134 | + config = PostgresConnectionConfig(host="h", database="d", username="u", password="p", port=5432) |
| 135 | + assert config.to_connection_string() == "postgres://u:p@h:5432/d" |
| 136 | + |
| 137 | + # With username but no password |
| 138 | + config = PostgresConnectionConfig(host="h", database="d", username="u", port=5432) |
| 139 | + assert config.to_connection_string() == "postgres://u@h:5432/d" |
| 140 | + |
| 141 | +def test_connection_string_all_pg_params(): |
| 142 | + """Test that all pg-specific boolean and string params are in the conn string.""" |
| 143 | + config = PostgresConnectionConfig( |
| 144 | + host="h", database="d", port=1, |
| 145 | + sslmode='require', |
| 146 | + sslcert='cert.pem', |
| 147 | + sslkey='key.pem', |
| 148 | + sslrootcert='root.crt', |
| 149 | + sslcrl='crl.pem', |
| 150 | + sslcompression=True, |
| 151 | + application_name='app', |
| 152 | + target_session_attrs='primary', |
| 153 | + connect_timeout=15, |
| 154 | + client_encoding='latin1', |
| 155 | + service='my_service', |
| 156 | + gssencmode='prefer', |
| 157 | + channel_binding='require' |
| 158 | + ) |
| 159 | + conn_str = config.to_connection_string() |
| 160 | + |
| 161 | + assert "sslmode=require" in conn_str |
| 162 | + assert "sslcert=cert.pem" in conn_str |
| 163 | + assert "sslkey=key.pem" in conn_str |
| 164 | + assert "sslrootcert=root.crt" in conn_str |
| 165 | + assert "sslcrl=crl.pem" in conn_str |
| 166 | + assert "sslcompression=True" in conn_str |
| 167 | + assert "application_name=app" in conn_str |
| 168 | + assert "target_session_attrs=primary" in conn_str |
| 169 | + assert "connect_timeout=15" in conn_str |
| 170 | + assert "client_encoding=latin1" in conn_str |
| 171 | + assert "service=my_service" in conn_str |
| 172 | + assert "gssencmode=prefer" in conn_str |
| 173 | + assert "channel_binding=require" in conn_str |
| 174 | + |
0 commit comments