Skip to content

Commit 3d1bb14

Browse files
author
Bernd Warmuth
committed
test: added unit test for ChannelBuilder
Signed-off-by: Bernd Warmuth <[email protected]>
1 parent 22a5bc9 commit 3d1bb14

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package dev.openfeature.contrib.providers.flagd.resolver.common;
2+
3+
import dev.openfeature.contrib.providers.flagd.FlagdOptions;
4+
import io.grpc.ManagedChannel;
5+
import io.grpc.netty.GrpcSslContexts;
6+
import io.grpc.netty.NettyChannelBuilder;
7+
import io.netty.channel.epoll.Epoll;
8+
import io.netty.channel.epoll.EpollDomainSocketChannel;
9+
import io.netty.channel.epoll.EpollEventLoopGroup;
10+
import io.netty.channel.unix.DomainSocketAddress;
11+
import io.netty.handler.ssl.SslContextBuilder;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.condition.EnabledOnOs;
14+
import org.junit.jupiter.api.condition.OS;
15+
import org.junit.jupiter.params.ParameterizedTest;
16+
import org.junit.jupiter.params.provider.ValueSource;
17+
import org.mockito.MockedStatic;
18+
19+
import javax.net.ssl.SSLKeyException;
20+
import java.io.File;
21+
import java.util.concurrent.TimeUnit;
22+
23+
import static org.assertj.core.api.Assertions.assertThat;
24+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
25+
import static org.mockito.Mockito.any;
26+
import static org.mockito.Mockito.anyLong;
27+
import static org.mockito.Mockito.anyString;
28+
import static org.mockito.Mockito.mock;
29+
import static org.mockito.Mockito.mockStatic;
30+
import static org.mockito.Mockito.verify;
31+
import static org.mockito.Mockito.when;
32+
33+
public class ChannelBuilderTest {
34+
35+
@Test
36+
@EnabledOnOs(OS.LINUX)
37+
void testNettyChannel_withSocketPath() {
38+
try (MockedStatic<Epoll> epollMock = mockStatic(Epoll.class);
39+
MockedStatic<NettyChannelBuilder> nettyMock = mockStatic(NettyChannelBuilder.class)) {
40+
41+
// Mocks
42+
epollMock.when(Epoll::isAvailable).thenReturn(true);
43+
NettyChannelBuilder mockBuilder = mock(NettyChannelBuilder.class);
44+
ManagedChannel mockChannel = mock(ManagedChannel.class);
45+
46+
nettyMock.when(() -> NettyChannelBuilder.forAddress(any(DomainSocketAddress.class)))
47+
.thenReturn(mockBuilder);
48+
49+
when(mockBuilder.keepAliveTime(anyLong(), any(TimeUnit.class))).thenReturn(mockBuilder);
50+
when(mockBuilder.eventLoopGroup(any(EpollEventLoopGroup.class))).thenReturn(mockBuilder);
51+
when(mockBuilder.channelType(EpollDomainSocketChannel.class)).thenReturn(mockBuilder);
52+
when(mockBuilder.usePlaintext()).thenReturn(mockBuilder);
53+
when(mockBuilder.build()).thenReturn(mockChannel);
54+
55+
// Input options
56+
FlagdOptions options = FlagdOptions.builder()
57+
.socketPath("/path/to/socket")
58+
.keepAlive(1000)
59+
.build();
60+
61+
// Call method under test
62+
ManagedChannel channel = ChannelBuilder.nettyChannel(options);
63+
64+
// Assertions
65+
assertThat(channel).isEqualTo(mockChannel);
66+
nettyMock.verify(() -> NettyChannelBuilder.forAddress(new DomainSocketAddress("/path/to/socket")));
67+
verify(mockBuilder).keepAliveTime(1000, TimeUnit.MILLISECONDS);
68+
verify(mockBuilder).eventLoopGroup(any(EpollEventLoopGroup.class));
69+
verify(mockBuilder).channelType(EpollDomainSocketChannel.class);
70+
verify(mockBuilder).usePlaintext();
71+
verify(mockBuilder).build();
72+
}
73+
}
74+
75+
@Test
76+
void testNettyChannel_withTlsAndCert() {
77+
try (MockedStatic<NettyChannelBuilder> nettyMock = mockStatic(NettyChannelBuilder.class)) {
78+
// Mocks
79+
NettyChannelBuilder mockBuilder = mock(NettyChannelBuilder.class);
80+
ManagedChannel mockChannel = mock(ManagedChannel.class);
81+
nettyMock.when(() -> NettyChannelBuilder.forTarget("localhost:8080"))
82+
.thenReturn(mockBuilder);
83+
84+
when(mockBuilder.keepAliveTime(anyLong(), any(TimeUnit.class))).thenReturn(mockBuilder);
85+
when(mockBuilder.sslContext(any())).thenReturn(mockBuilder);
86+
when(mockBuilder.build()).thenReturn(mockChannel);
87+
88+
File mockCert = mock(File.class);
89+
when(mockCert.exists()).thenReturn(true);
90+
String path = "test-harness/ssl/custom-root-cert.crt";
91+
92+
File file = new File(path);
93+
String absolutePath = file.getAbsolutePath();
94+
// Input options
95+
FlagdOptions options = FlagdOptions.builder()
96+
.host("localhost")
97+
.port(8080)
98+
.keepAlive(5000)
99+
.tls(true)
100+
.certPath(absolutePath)
101+
.build();
102+
103+
// Call method under test
104+
ManagedChannel channel = ChannelBuilder.nettyChannel(options);
105+
106+
// Assertions
107+
assertThat(channel).isEqualTo(mockChannel);
108+
nettyMock.verify(() -> NettyChannelBuilder.forTarget("localhost:8080"));
109+
verify(mockBuilder).keepAliveTime(5000, TimeUnit.MILLISECONDS);
110+
verify(mockBuilder).sslContext(any());
111+
verify(mockBuilder).build();
112+
}
113+
}
114+
115+
@ParameterizedTest
116+
@ValueSource(strings = {"/incorrect/{uri}/;)"})
117+
void testNettyChannel_withInvalidTargetUri(String uri) {
118+
FlagdOptions options = FlagdOptions.builder()
119+
.targetUri(uri)
120+
.build();
121+
122+
assertThatThrownBy(() -> ChannelBuilder.nettyChannel(options))
123+
.isInstanceOf(GenericConfigException.class)
124+
.hasMessageContaining("Error with gRPC target string configuration");
125+
}
126+
127+
@Test
128+
void testNettyChannel_epollNotAvailable() {
129+
try (MockedStatic<Epoll> epollMock = mockStatic(Epoll.class)) {
130+
epollMock.when(Epoll::isAvailable).thenReturn(false);
131+
132+
FlagdOptions options = FlagdOptions.builder().socketPath("/path/to/socket").build();
133+
134+
assertThatThrownBy(() -> ChannelBuilder.nettyChannel(options))
135+
.isInstanceOf(IllegalStateException.class)
136+
.hasMessageContaining("unix socket cannot be used");
137+
}
138+
}
139+
140+
@Test
141+
void testNettyChannel_sslException() throws Exception {
142+
try (MockedStatic<NettyChannelBuilder> nettyMock = mockStatic(NettyChannelBuilder.class)) {
143+
NettyChannelBuilder mockBuilder = mock(NettyChannelBuilder.class);
144+
nettyMock.when(() -> NettyChannelBuilder.forTarget(anyString())).thenReturn(mockBuilder);
145+
try (MockedStatic<GrpcSslContexts> sslmock = mockStatic(GrpcSslContexts.class)) {
146+
SslContextBuilder sslMockBuilder = mock(SslContextBuilder.class);
147+
sslmock.when(GrpcSslContexts::forClient).thenReturn(sslMockBuilder);
148+
when(sslMockBuilder.build()).thenThrow(new SSLKeyException("Test SSL error"));
149+
when(mockBuilder.keepAliveTime(anyLong(), any(TimeUnit.class))).thenReturn(mockBuilder);
150+
151+
FlagdOptions options = FlagdOptions.builder().tls(true).build();
152+
153+
assertThatThrownBy(() -> ChannelBuilder.nettyChannel(options))
154+
.isInstanceOf(SslConfigException.class)
155+
.hasMessageContaining("Error with SSL configuration");
156+
}
157+
}
158+
}
159+
}

0 commit comments

Comments
 (0)