1+ /*
2+ * Copyright The OpenTelemetry Authors
3+ * SPDX-License-Identifier: Apache-2.0
4+ */
5+
6+ package io .opentelemetry .instrumentation .spring .autoconfigure .internal .instrumentation .jdbc ;
7+
8+ import static org .assertj .core .api .Assertions .assertThat ;
9+ import static org .mockito .Mockito .mock ;
10+ import static org .mockito .Mockito .when ;
11+
12+ import io .opentelemetry .api .OpenTelemetry ;
13+ import io .opentelemetry .sdk .autoconfigure .spi .ConfigProperties ;
14+ import io .opentelemetry .sdk .autoconfigure .spi .internal .DefaultConfigProperties ;
15+ import java .io .PrintWriter ;
16+ import java .sql .Connection ;
17+ import java .sql .SQLException ;
18+ import java .sql .SQLFeatureNotSupportedException ;
19+ import java .util .Collections ;
20+ import java .util .logging .Logger ;
21+ import javax .sql .DataSource ;
22+ import org .junit .jupiter .api .DisplayName ;
23+ import org .junit .jupiter .api .Test ;
24+ import org .springframework .aop .framework .AopProxyUtils ;
25+ import org .springframework .beans .factory .config .BeanPostProcessor ;
26+ import org .springframework .beans .factory .support .DefaultListableBeanFactory ;
27+
28+ class DataSourcePostProcessorTest {
29+
30+ private static final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory ();
31+
32+ static {
33+ beanFactory .registerSingleton ("openTelemetry" , OpenTelemetry .noop ());
34+ beanFactory .registerSingleton (
35+ "configProperties" , DefaultConfigProperties .createFromMap (Collections .emptyMap ()));
36+ }
37+
38+ @ Test
39+ @ DisplayName ("when processed bean is NOT of type DataSource should return Object unchanged" )
40+ void returnsObject () {
41+ BeanPostProcessor underTest =
42+ new DataSourcePostProcessor (
43+ beanFactory .getBeanProvider (OpenTelemetry .class ),
44+ beanFactory .getBeanProvider (ConfigProperties .class ));
45+
46+ Object nonDataSource = new Object ();
47+ assertThat (underTest .postProcessAfterInitialization (nonDataSource , "testObject" ))
48+ .isSameAs (nonDataSource );
49+ }
50+
51+ @ Test
52+ @ DisplayName ("when processed bean is of type DataSource should return DataSource proxy" )
53+ void returnsDataSourceProxy () {
54+ BeanPostProcessor underTest =
55+ new DataSourcePostProcessor (
56+ beanFactory .getBeanProvider (OpenTelemetry .class ),
57+ beanFactory .getBeanProvider (ConfigProperties .class ));
58+
59+ DataSource originalDataSource = new TestDataSource ();
60+
61+ Object result = underTest .postProcessAfterInitialization (originalDataSource , "testDataSource" );
62+
63+ assertThat (result ).isInstanceOf (DataSource .class );
64+ assertThat (result ).isNotSameAs (originalDataSource );
65+
66+ Object target = AopProxyUtils .getSingletonTarget (result );
67+ assertThat (target ).isSameAs (originalDataSource );
68+ }
69+
70+ @ Test
71+ @ DisplayName ("when processed bean is scoped proxy target should return unchanged" )
72+ void returnsScopedProxyTargetUnchanged () {
73+ BeanPostProcessor underTest =
74+ new DataSourcePostProcessor (
75+ beanFactory .getBeanProvider (OpenTelemetry .class ),
76+ beanFactory .getBeanProvider (ConfigProperties .class ));
77+
78+ DataSource dataSource = new TestDataSource ();
79+ String scopedTargetBeanName = "scopedTarget.testDataSource" ;
80+
81+ Object result = underTest .postProcessAfterInitialization (dataSource , scopedTargetBeanName );
82+
83+ assertThat (result ).isSameAs (dataSource );
84+ }
85+
86+ @ Test
87+ @ DisplayName ("proxy should delegate method calls to wrapped telemetry DataSource" )
88+ void proxyDelegatesMethodCalls () throws SQLException {
89+ BeanPostProcessor underTest =
90+ new DataSourcePostProcessor (
91+ beanFactory .getBeanProvider (OpenTelemetry .class ),
92+ beanFactory .getBeanProvider (ConfigProperties .class ));
93+
94+ DataSource originalDataSource = new TestDataSource ();
95+
96+ Object result = underTest .postProcessAfterInitialization (originalDataSource , "testDataSource" );
97+
98+ DataSource proxiedDataSource = (DataSource ) result ;
99+ Connection connection = proxiedDataSource .getConnection ();
100+
101+ assertThat (connection ).isNotNull ();
102+ }
103+
104+ private static class TestDataSource implements DataSource {
105+ @ Override
106+ public Connection getConnection () throws SQLException {
107+ Connection mockConnection = mock (Connection .class );
108+ when (mockConnection .getMetaData ()).thenReturn (mock (java .sql .DatabaseMetaData .class ));
109+ return mockConnection ;
110+ }
111+
112+ @ Override
113+ public Connection getConnection (String username , String password ) throws SQLException {
114+ return getConnection ();
115+ }
116+
117+ @ Override
118+ public PrintWriter getLogWriter () throws SQLException {
119+ return null ;
120+ }
121+
122+ @ Override
123+ public void setLogWriter (PrintWriter out ) throws SQLException {}
124+
125+ @ Override
126+ public void setLoginTimeout (int seconds ) throws SQLException {}
127+
128+ @ Override
129+ public int getLoginTimeout () throws SQLException {
130+ return 0 ;
131+ }
132+
133+ @ Override
134+ public Logger getParentLogger () throws SQLFeatureNotSupportedException {
135+ throw new SQLFeatureNotSupportedException ();
136+ }
137+
138+ @ Override
139+ public <T > T unwrap (Class <T > iface ) throws SQLException {
140+ throw new SQLException ("Not supported" );
141+ }
142+
143+ @ Override
144+ public boolean isWrapperFor (Class <?> iface ) throws SQLException {
145+ return false ;
146+ }
147+ }
148+ }
0 commit comments