24
24
import java .net .Socket ;
25
25
import java .time .Duration ;
26
26
27
+ import org .apache .commons .codec .binary .Hex ;
27
28
import org .apache .logging .log4j .Level ;
28
- import org .apache .logging .log4j .LogManager ;
29
29
import org .apache .logging .log4j .Logger ;
30
- import org .assertj .core .api .Assertions ;
30
+ import org .apache .logging .log4j .core .LogEvent ;
31
+ import org .apache .logging .log4j .core .LoggerContext ;
32
+ import org .apache .logging .log4j .core .appender .SocketAppender ;
33
+ import org .apache .logging .log4j .core .filter .AbstractFilter ;
34
+ import org .apache .logging .log4j .core .test .junit .LoggerContextSource ;
35
+ import org .apache .logging .log4j .core .test .junit .Named ;
36
+ import org .apache .logging .log4j .status .StatusLogger ;
37
+ import org .apache .logging .log4j .test .TestProperties ;
38
+ import org .apache .logging .log4j .test .junit .UsingStatusListener ;
39
+ import org .apache .logging .log4j .test .junit .UsingTestProperties ;
31
40
import org .awaitility .Awaitility ;
41
+ import org .awaitility .core .ConditionTimeoutException ;
42
+ import org .junit .jupiter .api .AfterAll ;
43
+ import org .junit .jupiter .api .BeforeAll ;
32
44
import org .junit .jupiter .api .Test ;
33
45
46
+ import static org .assertj .core .api .Assertions .assertThat ;
47
+
48
+ @ UsingStatusListener
49
+ @ UsingTestProperties
34
50
class JsonTemplateLayoutNullEventDelimiterTest {
35
51
36
- @ Test
37
- void test () throws Exception {
52
+ private static Logger LOGGER = StatusLogger .getLogger ();
53
+
54
+ private static TcpServer server ;
38
55
56
+ private static TestProperties props ;
57
+
58
+ @ BeforeAll
59
+ static void setup () throws IOException {
39
60
// Start the TCP server.
40
- try (final TcpServer server = new TcpServer (0 )) {
41
-
42
- // Set the configuration.
43
- System .setProperty (
44
- "serverPort" ,
45
- String .valueOf (server .getPort ()));
46
- System .setProperty (
47
- "log4j.configurationFile" ,
48
- "nullEventDelimitedJsonTemplateLayoutLogging.xml" );
49
-
50
- // Produce log events.
51
- final Logger logger = LogManager .getLogger (JsonTemplateLayoutNullEventDelimiterTest .class );
52
- logger .log (Level .INFO , "foo" );
53
- logger .log (Level .INFO , "bar" );
54
-
55
- // Set the expected bytes.
56
- final byte [] expectedBytes = {
57
- '"' , 'f' , 'o' , 'o' , '"' , '\0' ,
58
- '"' , 'b' , 'a' , 'r' , '"' , '\0'
59
- };
60
-
61
- // Wait for the log events.
61
+ server = new TcpServer (0 );
62
+ // Set the configuration.
63
+ props .setProperty ("serverPort" , server .getPort ());
64
+ }
65
+
66
+ @ AfterAll
67
+ static void cleanup () throws IOException {
68
+ // Stop the TCP server.
69
+ server .close ();
70
+ }
71
+
72
+ @ Test
73
+ @ LoggerContextSource
74
+ void test (final @ Named ("Socket" ) SocketAppender appender , final LoggerContext ctx ) throws Exception {
75
+ assertThat (appender ).isNotNull ();
76
+ appender .addFilter (new AbstractFilter () {
77
+ @ Override
78
+ public Result filter (LogEvent event ) {
79
+ LOGGER .info ("Sending message {}" , event .getMessage ());
80
+ return super .filter (event );
81
+ }
82
+ });
83
+ // Produce log events.
84
+ final Logger logger = ctx .getLogger (JsonTemplateLayoutNullEventDelimiterTest .class );
85
+ logger .log (Level .INFO , "foo" );
86
+ logger .log (Level .INFO , "bar" );
87
+
88
+ // Set the expected bytes.
89
+ final byte [] expectedBytes = {
90
+ '"' , 'f' , 'o' , 'o' , '"' , '\0' ,
91
+ '"' , 'b' , 'a' , 'r' , '"' , '\0'
92
+ };
93
+
94
+ // Wait for the log events.
95
+ try {
62
96
Awaitility
63
97
.await ()
64
98
.atMost (Duration .ofSeconds (10 ))
65
99
.pollDelay (Duration .ofSeconds (1 ))
66
100
.until (() -> server .getTotalReadByteCount () >= expectedBytes .length );
67
-
68
- // Verify the received log events.
69
- final byte [] actualBytes = server .getReceivedBytes ();
70
- Assertions .assertThat (actualBytes ).startsWith (expectedBytes );
71
-
101
+ } catch (final ConditionTimeoutException e ) {
102
+ LOGGER .info ("Timeout reached while waiting for {} bytes." , expectedBytes .length );
72
103
}
73
104
105
+ // Verify the received log events.
106
+ final byte [] actualBytes = server .getReceivedBytes ();
107
+ assertThat (actualBytes ).containsExactly (expectedBytes );
74
108
}
75
109
76
110
private static final class TcpServer extends Thread implements AutoCloseable {
@@ -90,6 +124,7 @@ private TcpServer(final int port) throws IOException {
90
124
serverSocket .setSoTimeout (5_000 );
91
125
setDaemon (true );
92
126
start ();
127
+ LOGGER .info ("TcpServer started on port {}." , port );
93
128
}
94
129
95
130
@ Override
@@ -98,21 +133,24 @@ public void run() {
98
133
try (final Socket socket = serverSocket .accept ()) {
99
134
final InputStream inputStream = socket .getInputStream ();
100
135
final byte [] buffer = new byte [1024 ];
101
- // noinspection InfiniteLoopStatement
102
136
while (true ) {
103
137
final int readByteCount = inputStream .read (buffer );
104
- if (readByteCount > 0 ) {
138
+ if (readByteCount != -1 ) {
139
+ LOGGER .info ("Received bytes {}." , () -> Hex .encodeHex (buffer , 0 , readByteCount , false ));
105
140
synchronized (this ) {
106
141
totalReadByteCount += readByteCount ;
107
142
outputStream .write (buffer , 0 , readByteCount );
108
143
}
144
+ } else {
145
+ break ;
109
146
}
110
147
}
111
148
}
112
149
} catch (final EOFException ignored ) {
113
150
// Socket is closed.
114
151
} catch (final Exception error ) {
115
152
if (!closed ) {
153
+ LOGGER .error ("TcpServer received an error." , error );
116
154
throw new RuntimeException (error );
117
155
}
118
156
}
0 commit comments