Skip to content

Commit 7ccc884

Browse files
committed
Add basic tests for LightweightDebugger and DebuggerWithSymbolTables
1 parent c78559f commit 7ccc884

File tree

2 files changed

+264
-0
lines changed

2 files changed

+264
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* DebuggerWithSymbolTablesTest.java
3+
*
4+
* This source file is part of the FoundationDB open source project
5+
*
6+
* Copyright 2015-2025 Apple Inc. and the FoundationDB project authors
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
21+
package com.apple.foundationdb.record.query.plan.cascades.debug;
22+
23+
import com.apple.foundationdb.record.query.plan.cascades.PlanContext;
24+
import com.apple.foundationdb.record.query.plan.cascades.PlannerPhase;
25+
import com.apple.foundationdb.record.query.plan.cascades.Reference;
26+
import com.apple.foundationdb.record.query.plan.cascades.expressions.SelectExpression;
27+
import com.apple.foundationdb.record.query.plan.cascades.values.LiteralValue;
28+
import org.junit.jupiter.api.BeforeEach;
29+
import org.junit.jupiter.api.Test;
30+
31+
import java.util.ArrayDeque;
32+
import java.util.Collections;
33+
34+
import static org.assertj.core.api.Assertions.assertThat;
35+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
36+
37+
class DebuggerWithSymbolTablesTest {
38+
private DebuggerWithSymbolTables debugger;
39+
40+
void setupDebugger() {
41+
Debugger.setDebugger(debugger);
42+
Debugger.setup();
43+
Debugger.withDebugger(d -> d.onQuery("SELECT * from A", PlanContext.EMPTY_CONTEXT));
44+
}
45+
46+
@BeforeEach
47+
void setUp() {
48+
debugger = DebuggerWithSymbolTables.withoutSanityChecks();
49+
setupDebugger();
50+
}
51+
52+
@Test
53+
void testOnQueryResetsState() {
54+
final EventState initialEventState = debugger.getCurrentEventState();
55+
final SymbolTables initialSymbolTables = debugger.getCurrentSymbolState();
56+
57+
StatsDebugger.withDebugger(d -> d.onQuery("SELECT * from B", PlanContext.EMPTY_CONTEXT));
58+
59+
assertThat(debugger.getCurrentEventState()).isNotSameAs(initialEventState);
60+
assertThat(debugger.getCurrentSymbolState()).isNotSameAs(initialSymbolTables);
61+
}
62+
63+
@Test
64+
void testOnEventUpdatesStatsMap() {
65+
StatsDebugger.withDebugger(
66+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
67+
PlannerPhase.REWRITING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.BEGIN))
68+
);
69+
StatsDebugger.withDebugger(
70+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
71+
PlannerPhase.REWRITING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.END))
72+
);
73+
StatsDebugger.withDebugger(
74+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
75+
PlannerPhase.PLANNING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.BEGIN))
76+
);
77+
StatsDebugger.withDebugger(
78+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
79+
PlannerPhase.PLANNING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.END))
80+
);
81+
StatsDebugger.withDebugger(
82+
d -> d.onEvent(Debugger.InsertIntoMemoEvent.newExp(
83+
new SelectExpression(LiteralValue.ofScalar(1), Collections.emptyList(), Collections.emptyList())))
84+
);
85+
86+
assertThat(debugger.getStatsMaps()).isNotEmpty();
87+
final StatsMaps statsMaps = debugger.getStatsMaps().get();
88+
assertThat(statsMaps.getEventWithStateClassStatsMapByPlannerPhase(PlannerPhase.REWRITING))
89+
.hasValueSatisfying(
90+
m -> assertThat(m).hasSize(1)
91+
.containsKey(Debugger.InitiatePlannerPhaseEvent.class)
92+
);
93+
assertThat(statsMaps.getEventWithStateClassStatsMapByPlannerPhase(PlannerPhase.PLANNING))
94+
.hasValueSatisfying(
95+
m -> assertThat(m).hasSize(1)
96+
.containsKey(Debugger.InitiatePlannerPhaseEvent.class)
97+
);
98+
assertThat(debugger.getStatsMaps().get().getEventWithoutStateClassStatsMap()).hasSize(1)
99+
.containsKey(Debugger.InsertIntoMemoEvent.class);
100+
}
101+
102+
@Test
103+
void testDebuggerWithEventRecording() {
104+
debugger = DebuggerWithSymbolTables.withRerecordEvents();
105+
setupDebugger();
106+
107+
StatsDebugger.withDebugger(
108+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
109+
PlannerPhase.REWRITING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.BEGIN))
110+
);
111+
StatsDebugger.withDebugger(
112+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
113+
PlannerPhase.REWRITING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.END))
114+
);
115+
116+
assertThat(debugger.getCurrentEventState().getEvents()).hasSize(2);
117+
assertThat(debugger.getCurrentEventState().getEventProtos()).hasSize(2);
118+
}
119+
120+
@Test
121+
void testDebuggerWithSanityChecksEnabled() {
122+
debugger = DebuggerWithSymbolTables.withSanityChecks();
123+
setupDebugger();
124+
125+
assertThatThrownBy(() -> Debugger.sanityCheck(() -> { throw new RuntimeException(); }))
126+
.isInstanceOf(RuntimeException.class);
127+
}
128+
129+
@Test
130+
void testOnDoneResetsEventState() {
131+
final EventState initialEventState = debugger.getCurrentEventState();
132+
final SymbolTables initialSymbolTables = debugger.getCurrentSymbolState();
133+
134+
StatsDebugger.withDebugger(Debugger::onDone);
135+
136+
assertThat(debugger.getCurrentEventState()).isNotSameAs(initialEventState);
137+
assertThat(debugger.getCurrentSymbolState()).isNotSameAs(initialSymbolTables);
138+
}
139+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* LightweightDebuggerTest.java
3+
*
4+
* This source file is part of the FoundationDB open source project
5+
*
6+
* Copyright 2015-2025 Apple Inc. and the FoundationDB project authors
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
21+
package com.apple.foundationdb.record.query.plan.cascades.debug;
22+
23+
import com.apple.foundationdb.record.query.plan.cascades.PlanContext;
24+
import com.apple.foundationdb.record.query.plan.cascades.PlannerPhase;
25+
import com.apple.foundationdb.record.query.plan.cascades.Reference;
26+
import com.apple.foundationdb.record.query.plan.cascades.expressions.SelectExpression;
27+
import com.apple.foundationdb.record.query.plan.cascades.values.LiteralValue;
28+
import org.junit.jupiter.api.BeforeEach;
29+
import org.junit.jupiter.api.Test;
30+
31+
import java.util.ArrayDeque;
32+
import java.util.Collections;
33+
34+
import static org.assertj.core.api.Assertions.assertThat;
35+
import static org.assertj.core.api.Assertions.assertThatCode;
36+
37+
class LightweightDebuggerTest {
38+
private LightweightDebugger debugger;
39+
40+
@BeforeEach
41+
void setUp() {
42+
debugger = new LightweightDebugger();
43+
Debugger.setDebugger(debugger);
44+
Debugger.setup();
45+
StatsDebugger.withDebugger(d -> d.onQuery("SELECT * from A", PlanContext.EMPTY_CONTEXT));
46+
}
47+
48+
@Test
49+
void testOnQueryResetsState() {
50+
final EventState initialState = debugger.getCurrentEventState();
51+
52+
StatsDebugger.withDebugger(d -> d.onQuery("SELECT * FROM B", PlanContext.EMPTY_CONTEXT));
53+
54+
assertThat(debugger.getCurrentEventState()).isNotSameAs(initialState);
55+
}
56+
57+
@Test
58+
void testOnEventUpdatesStatsMap() {
59+
StatsDebugger.withDebugger(
60+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
61+
PlannerPhase.REWRITING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.BEGIN))
62+
);
63+
StatsDebugger.withDebugger(
64+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
65+
PlannerPhase.REWRITING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.END))
66+
);
67+
StatsDebugger.withDebugger(
68+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
69+
PlannerPhase.PLANNING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.BEGIN))
70+
);
71+
StatsDebugger.withDebugger(
72+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
73+
PlannerPhase.PLANNING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.END))
74+
);
75+
StatsDebugger.withDebugger(
76+
d -> d.onEvent(Debugger.InsertIntoMemoEvent.newExp(
77+
new SelectExpression(LiteralValue.ofScalar(1), Collections.emptyList(), Collections.emptyList())))
78+
);
79+
80+
assertThat(debugger.getStatsMaps()).isNotEmpty();
81+
final StatsMaps statsMaps = debugger.getStatsMaps().get();
82+
assertThat(statsMaps.getEventWithStateClassStatsMapByPlannerPhase(PlannerPhase.REWRITING))
83+
.hasValueSatisfying(
84+
m -> assertThat(m).hasSize(1)
85+
.containsKey(Debugger.InitiatePlannerPhaseEvent.class)
86+
);
87+
assertThat(statsMaps.getEventWithStateClassStatsMapByPlannerPhase(PlannerPhase.PLANNING))
88+
.hasValueSatisfying(
89+
m -> assertThat(m).hasSize(1)
90+
.containsKey(Debugger.InitiatePlannerPhaseEvent.class)
91+
);
92+
assertThat(debugger.getStatsMaps().get().getEventWithoutStateClassStatsMap()).hasSize(1)
93+
.containsKey(Debugger.InsertIntoMemoEvent.class);
94+
}
95+
96+
@Test
97+
void testEventsArentStoredByLightweightDebugger() {
98+
StatsDebugger.withDebugger(
99+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
100+
PlannerPhase.REWRITING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.BEGIN))
101+
);
102+
StatsDebugger.withDebugger(
103+
d -> d.onEvent(new Debugger.InitiatePlannerPhaseEvent(
104+
PlannerPhase.REWRITING, Reference.empty(), new ArrayDeque<>(), Debugger.Location.END))
105+
);
106+
107+
assertThat(debugger.getCurrentEventState().getEvents()).isNull();
108+
assertThat(debugger.getCurrentEventState().getEventProtos()).isNull();
109+
}
110+
111+
@Test
112+
void testLightweightDebuggerDisablesSanityChecks() {
113+
assertThatCode(() -> Debugger.sanityCheck(() -> { throw new RuntimeException(); }))
114+
.doesNotThrowAnyException();
115+
}
116+
117+
@Test
118+
void testOnDoneResetsEventState() {
119+
final EventState initialState = debugger.getCurrentEventState();
120+
121+
StatsDebugger.withDebugger(Debugger::onDone);
122+
123+
assertThat(debugger.getCurrentEventState()).isNotSameAs(initialState);
124+
}
125+
}

0 commit comments

Comments
 (0)