|
9 | 9 | import org.apache.calcite.sql.type.SqlTypeName; |
10 | 10 | import org.junit.jupiter.api.Test; |
11 | 11 | import org.junit.jupiter.api.extension.ExtendWith; |
| 12 | +import org.mockito.ArgumentCaptor; |
12 | 13 | import org.mockito.Mock; |
13 | 14 | import org.mockito.MockedStatic; |
14 | 15 | import org.mockito.junit.jupiter.MockitoExtension; |
|
17 | 18 | import java.sql.SQLNonTransientException; |
18 | 19 | import java.util.Collections; |
19 | 20 | import java.util.List; |
| 21 | +import java.util.Map; |
20 | 22 | import java.util.Properties; |
21 | 23 |
|
22 | 24 | import static org.assertj.core.api.Assertions.assertThat; |
@@ -187,6 +189,34 @@ void updateIfExistsBypassesTheGuardAndDoesNotConsultExists() throws SQLException |
187 | 189 | verify(deployer, never()).exists(); |
188 | 190 | } |
189 | 191 |
|
| 192 | + @Test |
| 193 | + void createMergesConnectionHintsIntoTableOptionsWithHintsWinning() throws SQLException { |
| 194 | + // Connection hints must be merged into the table options handed to the deployers, and a hint |
| 195 | + // must override a caller-supplied option of the same key so callers can't override |
| 196 | + // connection-level properties (impersonation guard). |
| 197 | + DatabaseConfigResolver resolver = stubResolver(); |
| 198 | + resolvers.when(() -> DatabaseConfigResolvers.forProperties(any())).thenReturn(resolver); |
| 199 | + deployment.when(() -> DeploymentService.parseHints(any())) |
| 200 | + .thenReturn(Map.of("owner", "connection-user", "hintOnly", "hintValue")); |
| 201 | + Deployer deployer = mock(Deployer.class); |
| 202 | + when(deployer.exists()).thenReturn(false); |
| 203 | + List<Deployer> deployers = Collections.singletonList(deployer); |
| 204 | + deployment.when(() -> DeploymentService.deployers(any(Source.class), any(DeploymentContext.class))) |
| 205 | + .thenReturn(deployers); |
| 206 | + |
| 207 | + Map<String, String> callerOptions = Map.of("owner", "caller-attempt", "callerOnly", "callerValue"); |
| 208 | + TableService.create(new Properties(), Collections.emptyList(), path, recordSchema(), |
| 209 | + callerOptions, false, false); |
| 210 | + |
| 211 | + ArgumentCaptor<Source> sourceCaptor = ArgumentCaptor.forClass(Source.class); |
| 212 | + deployment.verify(() -> |
| 213 | + DeploymentService.deployers(sourceCaptor.capture(), any(DeploymentContext.class))); |
| 214 | + Map<String, String> mergedOptions = sourceCaptor.getValue().options(); |
| 215 | + assertThat(mergedOptions).containsEntry("callerOnly", "callerValue"); |
| 216 | + assertThat(mergedOptions).containsEntry("hintOnly", "hintValue"); |
| 217 | + assertThat(mergedOptions).containsEntry("owner", "connection-user"); |
| 218 | + } |
| 219 | + |
190 | 220 | private static Schema recordSchema() { |
191 | 221 | return new Schema.Parser().parse(RECORD_SCHEMA); |
192 | 222 | } |
|
0 commit comments