Skip to content
This repository was archived by the owner on Nov 11, 2022. It is now read-only.

Commit bdde374

Browse files
bchambersdavorbonaci
authored andcommitted
Change ExpectedLogs to include better stack-traces
Also add support for verifying the absence of a message. ----Release Notes---- [] ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=94922273
1 parent 6ec1a04 commit bdde374

4 files changed

Lines changed: 163 additions & 93 deletions

File tree

sdk/src/test/java/com/google/cloud/dataflow/sdk/options/PipelineOptionsFactoryTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,8 @@ public void testSetASingularAttributeUsingAListIsIgnoredWithoutStrictParsing() {
577577
String[] args = new String[] {
578578
"--diskSizeGb=100",
579579
"--diskSizeGb=200"};
580-
expectedLogs.expectWarn("Strict parsing is disabled, ignoring option");
581580
PipelineOptionsFactory.fromArgs(args).withoutStrictParsing().create();
581+
expectedLogs.verifyWarn("Strict parsing is disabled, ignoring option");
582582
}
583583

584584
@Test
@@ -610,8 +610,8 @@ public void testUsingArgumentWithUnknownPropertyIsNotAllowed() {
610610
@Test
611611
public void testUsingArgumentWithUnknownPropertyIsIgnoredWithoutStrictParsing() {
612612
String[] args = new String[] {"--unknownProperty=value"};
613-
expectedLogs.expectWarn("missing a property named 'unknownProperty'");
614613
PipelineOptionsFactory.fromArgs(args).withoutStrictParsing().create();
614+
expectedLogs.verifyWarn("missing a property named 'unknownProperty'");
615615
}
616616

617617
@Test
@@ -625,8 +625,8 @@ public void testUsingArgumentStartingWithIllegalCharacterIsNotAllowed() {
625625
@Test
626626
public void testUsingArgumentStartingWithIllegalCharacterIsIgnoredWithoutStrictParsing() {
627627
String[] args = new String[] {" --diskSizeGb=100"};
628-
expectedLogs.expectWarn("Strict parsing is disabled, ignoring option");
629628
PipelineOptionsFactory.fromArgs(args).withoutStrictParsing().create();
629+
expectedLogs.verifyWarn("Strict parsing is disabled, ignoring option");
630630
}
631631

632632
@Test
@@ -652,8 +652,8 @@ public void testUsingArgumentWithInvalidNameIsNotAllowed() {
652652
@Test
653653
public void testUsingArgumentWithInvalidNameIsIgnoredWithoutStrictParsing() {
654654
String[] args = new String[] {"--=100"};
655-
expectedLogs.expectWarn("Strict parsing is disabled, ignoring option");
656655
PipelineOptionsFactory.fromArgs(args).withoutStrictParsing().create();
656+
expectedLogs.verifyWarn("Strict parsing is disabled, ignoring option");
657657
}
658658

659659
@Test

sdk/src/test/java/com/google/cloud/dataflow/sdk/runners/BlockingDataflowPipelineRunnerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ public synchronized boolean waitTillSet(long timeout) throws InterruptedExceptio
100100

101101
@Test
102102
public void testJobWaitComplete() throws IOException, InterruptedException {
103-
expectedLogs.expectInfo("Job finished with status DONE");
104103

105104
DataflowPipelineRunner mockDataflowPipelineRunner = mock(DataflowPipelineRunner.class);
106105
DataflowPipelineJob mockJob = mock(DataflowPipelineJob.class);
@@ -141,6 +140,7 @@ public void run() {
141140
mockWait.signalJobComplete();
142141
assertTrue("run() should return after job completion is mocked.",
143142
jobCompleted.waitTillSet(2000));
143+
expectedLogs.verifyInfo("Job finished with status DONE");
144144
}
145145

146146
@Test

sdk/src/test/java/com/google/cloud/dataflow/sdk/testing/ExpectedLogs.java

Lines changed: 107 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
import static org.junit.Assert.fail;
2020

21-
import com.google.common.collect.Lists;
22-
2321
import org.hamcrest.Description;
2422
import org.hamcrest.Matcher;
2523
import org.hamcrest.TypeSafeMatcher;
@@ -28,10 +26,12 @@
2826

2927
import java.util.Collection;
3028
import java.util.concurrent.ConcurrentLinkedDeque;
29+
import java.util.logging.Formatter;
3130
import java.util.logging.Handler;
3231
import java.util.logging.Level;
3332
import java.util.logging.LogRecord;
3433
import java.util.logging.Logger;
34+
import java.util.logging.SimpleFormatter;
3535

3636
import javax.annotation.concurrent.ThreadSafe;
3737

@@ -53,121 +53,168 @@ public static ExpectedLogs none(Class<?> klass) {
5353
}
5454

5555
/**
56-
* Expect a logging event at the trace level with the given message.
56+
* Verify a logging event at the trace level with the given message.
5757
*
5858
* @param substring The message to match against.
5959
*/
60-
public void expectTrace(String substring) {
61-
expect(Level.FINEST, substring);
60+
public void verifyTrace(String substring) {
61+
verify(Level.FINEST, substring);
6262
}
6363

6464
/**
65-
* Expect a logging event at the trace level with the given message and throwable.
65+
* Verify a logging event at the trace level with the given message and throwable.
6666
*
6767
* @param substring The message to match against.
6868
* @param t The throwable to match against.
6969
*/
70-
public void expectTrace(String substring, Throwable t) {
71-
expect(Level.FINEST, substring, t);
70+
public void verifyTrace(String substring, Throwable t) {
71+
verify(Level.FINEST, substring, t);
7272
}
7373

7474
/**
75-
* Expect a logging event at the debug level with the given message.
75+
* Verify a logging event at the debug level with the given message.
7676
*
7777
* @param substring The message to match against.
7878
*/
79-
public void expectDebug(String substring) {
80-
expect(Level.FINE, substring);
79+
public void verifyDebug(String substring) {
80+
verify(Level.FINE, substring);
8181
}
8282

8383
/**
84-
* Expect a logging event at the debug level with the given message and throwable.
84+
* Verify a logging event at the debug level with the given message and throwable.
8585
*
8686
* @param message The message to match against.
8787
* @param t The throwable to match against.
8888
*/
89-
public void expectDebug(String message, Throwable t) {
90-
expect(Level.FINE, message, t);
89+
public void verifyDebug(String message, Throwable t) {
90+
verify(Level.FINE, message, t);
9191
}
9292

9393
/**
94-
* Expect a logging event at the info level with the given message.
94+
* Verify a logging event at the info level with the given message.
95+
*
9596
* @param substring The message to match against.
9697
*/
97-
public void expectInfo(String substring) {
98-
expect(Level.INFO, substring);
98+
public void verifyInfo(String substring) {
99+
verify(Level.INFO, substring);
99100
}
100101

101102
/**
102-
* Expect a logging event at the info level with the given message and throwable.
103+
* Verify a logging event at the info level with the given message and throwable.
103104
*
104105
* @param message The message to match against.
105106
* @param t The throwable to match against.
106107
*/
107-
public void expectInfo(String message, Throwable t) {
108-
expect(Level.INFO, message, t);
108+
public void verifyInfo(String message, Throwable t) {
109+
verify(Level.INFO, message, t);
110+
}
111+
112+
/**
113+
* Verify a logging event at the warn level with the given message.
114+
*
115+
* @param substring The message to match against.
116+
*/
117+
public void verifyWarn(String substring) {
118+
verify(Level.WARNING, substring);
119+
}
120+
121+
/**
122+
* Verify a logging event at the warn level with the given message and throwable.
123+
*
124+
* @param substring The message to match against.
125+
* @param t The throwable to match against.
126+
*/
127+
public void verifyWarn(String substring, Throwable t) {
128+
verify(Level.WARNING, substring, t);
109129
}
110130

111131
/**
112-
* Expect a logging event at the warn level with the given message.
132+
* Verify a logging event at the error level with the given message.
113133
*
114134
* @param substring The message to match against.
115135
*/
116-
public void expectWarn(String substring) {
117-
expect(Level.WARNING, substring);
136+
public void verifyError(String substring) {
137+
verify(Level.SEVERE, substring);
118138
}
119139

120140
/**
121-
* Expect a logging event at the warn level with the given message and throwable.
141+
* Verify a logging event at the error level with the given message and throwable.
122142
*
123143
* @param substring The message to match against.
124144
* @param t The throwable to match against.
125145
*/
126-
public void expectWarn(String substring, Throwable t) {
127-
expect(Level.WARNING, substring, t);
146+
public void verifyError(String substring, Throwable t) {
147+
verify(Level.SEVERE, substring, t);
128148
}
129149

130150
/**
131-
* Expect a logging event at the error level with the given message.
151+
* Verify there are no logging events with messages containing the given substring.
132152
*
133153
* @param substring The message to match against.
134154
*/
135-
public void expectError(String substring) {
136-
expect(Level.SEVERE, substring);
155+
public void verifyNotLogged(String substring) {
156+
verifyNotLogged(matcher(substring));
137157
}
138158

139159
/**
140-
* Expect a logging event at the error level with the given message and throwable.
160+
* Verify there is no logging event at the error level with the given message and throwable.
141161
*
142162
* @param substring The message to match against.
143163
* @param t The throwable to match against.
144164
*/
145-
public void expectError(String substring, Throwable t) {
146-
expect(Level.SEVERE, substring, t);
165+
public void verifyNoError(String substring, Throwable t) {
166+
verifyNo(Level.SEVERE, substring, t);
167+
}
168+
169+
private void verify(final Level level, final String substring) {
170+
verifyLogged(matcher(level, substring));
147171
}
148172

149-
private void expect(final Level level, final String substring) {
150-
expectations.add(new TypeSafeMatcher<LogRecord>() {
173+
private TypeSafeMatcher<LogRecord> matcher(final String substring) {
174+
return new TypeSafeMatcher<LogRecord>() {
175+
@Override
176+
public void describeTo(Description description) {
177+
description.appendText(String.format("log message containing message [%s]", substring));
178+
}
179+
180+
@Override
181+
protected boolean matchesSafely(LogRecord item) {
182+
return item.getMessage().contains(substring);
183+
}
184+
};
185+
}
186+
187+
private TypeSafeMatcher<LogRecord> matcher(final Level level, final String substring) {
188+
return new TypeSafeMatcher<LogRecord>() {
151189
@Override
152190
public void describeTo(Description description) {
153191
description.appendText(String.format(
154-
"Expected log message of level [%s] containing message [%s]", level, substring));
192+
"log message of level [%s] containing message [%s]", level, substring));
155193
}
156194

157195
@Override
158196
protected boolean matchesSafely(LogRecord item) {
159197
return level.equals(item.getLevel())
160198
&& item.getMessage().contains(substring);
161199
}
162-
});
200+
};
201+
}
202+
203+
private void verify(final Level level, final String substring, final Throwable throwable) {
204+
verifyLogged(matcher(level, substring, throwable));
163205
}
164206

165-
private void expect(final Level level, final String substring, final Throwable throwable) {
166-
expectations.add(new TypeSafeMatcher<LogRecord>() {
207+
private void verifyNo(final Level level, final String substring, final Throwable throwable) {
208+
verifyNotLogged(matcher(level, substring, throwable));
209+
}
210+
211+
private TypeSafeMatcher<LogRecord> matcher(
212+
final Level level, final String substring, final Throwable throwable) {
213+
return new TypeSafeMatcher<LogRecord>() {
167214
@Override
168215
public void describeTo(Description description) {
169216
description.appendText(String.format(
170-
"Expected log message of level [%s] containg message [%s] with exception [%s] "
217+
"log message of level [%s] containg message [%s] with exception [%s] "
171218
+ "containing message [%s]",
172219
level, substring, throwable.getClass(), throwable.getMessage()));
173220
}
@@ -179,7 +226,26 @@ protected boolean matchesSafely(LogRecord item) {
179226
&& item.getThrown().getClass().equals(throwable.getClass())
180227
&& item.getThrown().getMessage().contains(throwable.getMessage());
181228
}
182-
});
229+
};
230+
}
231+
232+
private void verifyLogged(Matcher<LogRecord> matcher) {
233+
for (LogRecord record : logSaver.getLogs()) {
234+
if (matcher.matches(record)) {
235+
return;
236+
}
237+
}
238+
239+
fail(String.format("Missing match for [%s]", matcher));
240+
}
241+
242+
private void verifyNotLogged(Matcher<LogRecord> matcher) {
243+
// Don't use Matchers.everyItem(Matchers.not(matcher)) because it doesn't format the logRecord
244+
for (LogRecord record : logSaver.getLogs()) {
245+
if (matcher.matches(record)) {
246+
fail(String.format("Unexpected match of [%s]: [%s]", matcher, logFormatter.format(record)));
247+
}
248+
}
183249
}
184250

185251
@Override
@@ -193,30 +259,16 @@ protected void before() throws Throwable {
193259
protected void after() {
194260
log.removeHandler(logSaver);
195261
log.setLevel(previousLevel);
196-
Collection<Matcher<LogRecord>> missingExpecations = Lists.newArrayList();
197-
FOUND: for (Matcher<LogRecord> expectation : expectations) {
198-
for (LogRecord log : logSaver.getLogs()) {
199-
if (expectation.matches(log)) {
200-
continue FOUND;
201-
}
202-
}
203-
missingExpecations.add(expectation);
204-
}
205-
206-
if (!missingExpecations.isEmpty()) {
207-
fail(String.format("Missed logging expectations: %s", missingExpecations));
208-
}
209262
}
210263

211264
private final Logger log;
212265
private final LogSaver logSaver;
213-
private final Collection<Matcher<LogRecord>> expectations;
266+
private final Formatter logFormatter = new SimpleFormatter();
214267
private Level previousLevel;
215268

216269
private ExpectedLogs(Class<?> klass) {
217270
log = Logger.getLogger(klass.getName());
218271
logSaver = new LogSaver();
219-
expectations = Lists.newArrayList();
220272
}
221273

222274
/**

0 commit comments

Comments
 (0)