1919import static org .assertj .core .api .Assertions .assertThat ;
2020
2121import java .math .BigDecimal ;
22+ import java .util .List ;
23+ import java .util .function .Supplier ;
24+ import java .util .stream .Collectors ;
2225import java .util .stream .Stream ;
26+ import org .apache .logging .log4j .Level ;
27+ import org .apache .logging .log4j .status .StatusData ;
28+ import org .apache .logging .log4j .test .ListStatusListener ;
2329import org .apache .logging .log4j .test .junit .Mutable ;
2430import org .apache .logging .log4j .test .junit .SerialUtil ;
31+ import org .apache .logging .log4j .test .junit .UsingStatusListener ;
2532import org .junit .jupiter .api .Test ;
2633import org .junit .jupiter .params .ParameterizedTest ;
2734import org .junit .jupiter .params .provider .MethodSource ;
2835
29- public class ParameterizedMessageTest {
36+ @ UsingStatusListener
37+ class ParameterizedMessageTest {
38+
39+ final ListStatusListener statusListener ;
40+
41+ ParameterizedMessageTest (ListStatusListener statusListener ) {
42+ this .statusListener = statusListener ;
43+ }
3044
3145 @ Test
32- public void testNoArgs () {
46+ void testNoArgs () {
3347 final String testMsg = "Test message {}" ;
3448 ParameterizedMessage msg = new ParameterizedMessage (testMsg , (Object []) null );
3549 String result = msg .getFormattedMessage ();
@@ -41,7 +55,7 @@ public void testNoArgs() {
4155 }
4256
4357 @ Test
44- public void testZeroLength () {
58+ void testZeroLength () {
4559 final String testMsg = "" ;
4660 ParameterizedMessage msg = new ParameterizedMessage (testMsg , new Object [] {"arg" });
4761 String result = msg .getFormattedMessage ();
@@ -53,7 +67,7 @@ public void testZeroLength() {
5367 }
5468
5569 @ Test
56- public void testOneCharLength () {
70+ void testOneCharLength () {
5771 final String testMsg = "d" ;
5872 ParameterizedMessage msg = new ParameterizedMessage (testMsg , new Object [] {"arg" });
5973 String result = msg .getFormattedMessage ();
@@ -65,71 +79,71 @@ public void testOneCharLength() {
6579 }
6680
6781 @ Test
68- public void testFormat3StringArgs () {
82+ void testFormat3StringArgs () {
6983 final String testMsg = "Test message {}{} {}" ;
7084 final String [] args = {"a" , "b" , "c" };
7185 final String result = ParameterizedMessage .format (testMsg , args );
7286 assertThat (result ).isEqualTo ("Test message ab c" );
7387 }
7488
7589 @ Test
76- public void testFormatNullArgs () {
90+ void testFormatNullArgs () {
7791 final String testMsg = "Test message {} {} {} {} {} {}" ;
7892 final String [] args = {"a" , null , "c" , null , null , null };
7993 final String result = ParameterizedMessage .format (testMsg , args );
8094 assertThat (result ).isEqualTo ("Test message a null c null null null" );
8195 }
8296
8397 @ Test
84- public void testFormatStringArgsIgnoresSuperfluousArgs () {
98+ void testFormatStringArgsIgnoresSuperfluousArgs () {
8599 final String testMsg = "Test message {}{} {}" ;
86100 final String [] args = {"a" , "b" , "c" , "unnecessary" , "superfluous" };
87101 final String result = ParameterizedMessage .format (testMsg , args );
88102 assertThat (result ).isEqualTo ("Test message ab c" );
89103 }
90104
91105 @ Test
92- public void testFormatStringArgsWithEscape () {
106+ void testFormatStringArgsWithEscape () {
93107 final String testMsg = "Test message \\ {}{} {}" ;
94108 final String [] args = {"a" , "b" , "c" };
95109 final String result = ParameterizedMessage .format (testMsg , args );
96110 assertThat (result ).isEqualTo ("Test message {}a b" );
97111 }
98112
99113 @ Test
100- public void testFormatStringArgsWithTrailingEscape () {
114+ void testFormatStringArgsWithTrailingEscape () {
101115 final String testMsg = "Test message {}{} {}\\ " ;
102116 final String [] args = {"a" , "b" , "c" };
103117 final String result = ParameterizedMessage .format (testMsg , args );
104118 assertThat (result ).isEqualTo ("Test message ab c\\ " );
105119 }
106120
107121 @ Test
108- public void testFormatStringArgsWithTrailingText () {
122+ void testFormatStringArgsWithTrailingText () {
109123 final String testMsg = "Test message {}{} {}Text" ;
110124 final String [] args = {"a" , "b" , "c" };
111125 final String result = ParameterizedMessage .format (testMsg , args );
112126 assertThat (result ).isEqualTo ("Test message ab cText" );
113127 }
114128
115129 @ Test
116- public void testFormatStringArgsWithTrailingEscapedEscape () {
130+ void testFormatStringArgsWithTrailingEscapedEscape () {
117131 final String testMsg = "Test message {}{} {}\\ \\ " ;
118132 final String [] args = {"a" , "b" , "c" };
119133 final String result = ParameterizedMessage .format (testMsg , args );
120134 assertThat (result ).isEqualTo ("Test message ab c\\ " );
121135 }
122136
123137 @ Test
124- public void testFormatStringArgsWithEscapedEscape () {
138+ void testFormatStringArgsWithEscapedEscape () {
125139 final String testMsg = "Test message \\ \\ {}{} {}" ;
126140 final String [] args = {"a" , "b" , "c" };
127141 final String result = ParameterizedMessage .format (testMsg , args );
128142 assertThat (result ).isEqualTo ("Test message \\ ab c" );
129143 }
130144
131145 @ Test
132- public void testSafeWithMutableParams () { // LOG4J2-763
146+ void testSafeWithMutableParams () { // LOG4J2-763
133147 final String testMsg = "Test message {}" ;
134148 final Mutable param = new Mutable ().set ("abc" );
135149 final ParameterizedMessage msg = new ParameterizedMessage (testMsg , param );
@@ -170,4 +184,51 @@ void testSerializable(final Object arg) {
170184 assertThat (actual ).isInstanceOf (ParameterizedMessage .class );
171185 assertThat (actual .getFormattedMessage ()).isEqualTo (expected .getFormattedMessage ());
172186 }
187+
188+ static Stream <Object []> testCasesForInsufficientFormatArgs () {
189+ return Stream .of (new Object [] {1 , "foo {}" }, new Object [] {2 , "bar {}{}" });
190+ }
191+
192+ @ ParameterizedTest
193+ @ MethodSource ("testCasesForInsufficientFormatArgs" )
194+ void formatTo_should_fail_on_insufficient_args (final int placeholderCount , final String pattern ) {
195+ final int argCount = placeholderCount - 1 ;
196+ verifyFormattingFailureOnInsufficientArgs (placeholderCount , pattern , argCount , () -> {
197+ final ParameterizedMessage message = new ParameterizedMessage (pattern , new Object [argCount ]);
198+ final StringBuilder buffer = new StringBuilder ();
199+ message .formatTo (buffer );
200+ return buffer .toString ();
201+ });
202+ }
203+
204+ @ ParameterizedTest
205+ @ MethodSource ("testCasesForInsufficientFormatArgs" )
206+ void format_should_fail_on_insufficient_args (final int placeholderCount , final String pattern ) {
207+ final int argCount = placeholderCount - 1 ;
208+ verifyFormattingFailureOnInsufficientArgs (
209+ placeholderCount , pattern , argCount , () -> ParameterizedMessage .format (pattern , new Object [argCount ]));
210+ }
211+
212+ private void verifyFormattingFailureOnInsufficientArgs (
213+ final int placeholderCount ,
214+ final String pattern ,
215+ final int argCount ,
216+ final Supplier <String > formattedMessageSupplier ) {
217+
218+ // Verify the formatted message
219+ final String formattedMessage = formattedMessageSupplier .get ();
220+ assertThat (formattedMessage ).isEqualTo (pattern );
221+
222+ // Verify the logged failure
223+ final List <StatusData > statusDataList = statusListener .getStatusData ().collect (Collectors .toList ());
224+ assertThat (statusDataList ).hasSize (1 );
225+ final StatusData statusData = statusDataList .get (0 );
226+ assertThat (statusData .getLevel ()).isEqualTo (Level .ERROR );
227+ assertThat (statusData .getMessage ().getFormattedMessage ()).isEqualTo ("Unable to format msg: %s" , pattern );
228+ assertThat (statusData .getThrowable ())
229+ .isInstanceOf (IllegalArgumentException .class )
230+ .hasMessage (
231+ "found %d argument placeholders, but provided %d for pattern `%s`" ,
232+ placeholderCount , argCount , pattern );
233+ }
173234}
0 commit comments