From 877d45f6061387b80e4c7ea2866be77fa0df856d Mon Sep 17 00:00:00 2001 From: Sara Adams Date: Thu, 23 May 2024 14:26:39 +0200 Subject: [PATCH 1/2] [Core] Avoid NPEs on creating events When creating trace event format events, the code used to throw NullPointerExceptions when trying to construct an event from a JsonObject that was missing required members. This change adds static `fromJson` methods, which check the members exist, or otherwise throw an IllegalArgumentException. It also adds some basic tests for the Event classes. Signed-off-by: Sara Adams --- .../analyzer/bazelprofile/ProfileThread.java | 6 +- .../traceeventformat/CompleteEvent.java | 83 ++++++++++++++++--- .../traceeventformat/CounterEvent.java | 63 ++++++++++++-- .../traceeventformat/InstantEvent.java | 56 ++++++++++++- .../analyzer/traceeventformat/BUILD | 12 +++ .../traceeventformat/CompleteEventTest.java | 78 +++++++++++++++++ .../traceeventformat/CounterEventTest.java | 49 +++++++++++ .../traceeventformat/InstantEventTest.java | 45 ++++++++++ .../TraceEventFormatTestSuite.java | 26 ++++++ 9 files changed, 396 insertions(+), 22 deletions(-) create mode 100644 analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/BUILD create mode 100644 analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/CompleteEventTest.java create mode 100644 analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/CounterEventTest.java create mode 100644 analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/InstantEventTest.java create mode 100644 analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/TraceEventFormatTestSuite.java diff --git a/analyzer/java/com/engflow/bazel/invocation/analyzer/bazelprofile/ProfileThread.java b/analyzer/java/com/engflow/bazel/invocation/analyzer/bazelprofile/ProfileThread.java index 16efee5..6e46704 100644 --- a/analyzer/java/com/engflow/bazel/invocation/analyzer/bazelprofile/ProfileThread.java +++ b/analyzer/java/com/engflow/bazel/invocation/analyzer/bazelprofile/ProfileThread.java @@ -117,14 +117,14 @@ public boolean addEvent(JsonObject event) { switch (event.get(TraceEventFormatConstants.EVENT_PHASE).getAsString()) { case TraceEventFormatConstants.PHASE_COMPLETE: // Complete events { - completeEvents.add(new CompleteEvent(event)); + completeEvents.add(CompleteEvent.fromJson(event)); break; } case "I": // Deprecated, fall-through case TraceEventFormatConstants.PHASE_INSTANT: // Instant events { - InstantEvent instantEvent = new InstantEvent(event); + InstantEvent instantEvent = InstantEvent.fromJson(event); List instantList = instants.compute( @@ -142,7 +142,7 @@ public boolean addEvent(JsonObject event) { case TraceEventFormatConstants.PHASE_COUNTER: // Counter events { - CounterEvent counterEvent = new CounterEvent(event); + CounterEvent counterEvent = CounterEvent.fromJson(event); List countList = counts.compute( diff --git a/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/CompleteEvent.java b/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/CompleteEvent.java index 5ab4e6c..e1f8893 100644 --- a/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/CompleteEvent.java +++ b/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/CompleteEvent.java @@ -18,13 +18,34 @@ import com.engflow.bazel.invocation.analyzer.time.TimeUtil; import com.engflow.bazel.invocation.analyzer.time.Timestamp; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; import com.google.gson.JsonObject; import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import javax.annotation.Nullable; +/** + * Complete events describe an event with a duration. + * + * @see specification + */ public class CompleteEvent { + @VisibleForTesting + static final List REQUIRED_JSON_MEMBERS = + List.of( + TraceEventFormatConstants.EVENT_TIMESTAMP, + TraceEventFormatConstants.EVENT_DURATION, + TraceEventFormatConstants.EVENT_THREAD_ID, + TraceEventFormatConstants.EVENT_PROCESS_ID); + @Nullable public final String name; @Nullable public final String category; public final Timestamp start; @@ -32,15 +53,56 @@ public class CompleteEvent { public final Timestamp end; public final int threadId; public final int processId; - public final ImmutableMap args; + public final Map args; + + public static CompleteEvent fromJson(JsonObject object) { + Preconditions.checkNotNull(object); + List missingMembers = Lists.newArrayList(); + for (String requiredMember : REQUIRED_JSON_MEMBERS) { + if (!object.has(requiredMember)) { + missingMembers.add(requiredMember); + } + } + if (!missingMembers.isEmpty()) { + throw new IllegalArgumentException( + "Missing members: " + Arrays.toString(missingMembers.toArray())); + } + + return new CompleteEvent( + object.has(TraceEventFormatConstants.EVENT_NAME) + ? object.get(TraceEventFormatConstants.EVENT_NAME).getAsString() + : null, + object.has(TraceEventFormatConstants.EVENT_CATEGORY) + ? object.get(TraceEventFormatConstants.EVENT_CATEGORY).getAsString() + : null, + Timestamp.ofMicros(object.get(TraceEventFormatConstants.EVENT_TIMESTAMP).getAsLong()), + TimeUtil.getDurationForMicros( + object.get(TraceEventFormatConstants.EVENT_DURATION).getAsLong()), + object.get(TraceEventFormatConstants.EVENT_THREAD_ID).getAsInt(), + object.get(TraceEventFormatConstants.EVENT_PROCESS_ID).getAsInt(), + object.has(TraceEventFormatConstants.EVENT_ARGUMENTS) + ? object + .get(TraceEventFormatConstants.EVENT_ARGUMENTS) + .getAsJsonObject() + .entrySet() + .stream() + .collect(toImmutableMap(e -> e.getKey(), e -> e.getValue().getAsString())) + : ImmutableMap.of()); + } + /** + * Parses a {@link CompleteEvent} from a JsonObject. + * + * @deprecated Use {@link #fromJson(JsonObject)} instead. + */ + @Deprecated public CompleteEvent(JsonObject object) { this( object.has(TraceEventFormatConstants.EVENT_NAME) - ? object.get(TraceEventFormatConstants.EVENT_NAME).getAsString().intern() + ? object.get(TraceEventFormatConstants.EVENT_NAME).getAsString() : null, object.has(TraceEventFormatConstants.EVENT_CATEGORY) - ? object.get(TraceEventFormatConstants.EVENT_CATEGORY).getAsString().intern() + ? object.get(TraceEventFormatConstants.EVENT_CATEGORY).getAsString() : null, Timestamp.ofMicros(object.get(TraceEventFormatConstants.EVENT_TIMESTAMP).getAsLong()), TimeUtil.getDurationForMicros( @@ -53,9 +115,7 @@ public CompleteEvent(JsonObject object) { .getAsJsonObject() .entrySet() .stream() - .collect( - toImmutableMap( - e -> e.getKey().intern(), e -> e.getValue().getAsString().intern())) + .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().getAsString())) : ImmutableMap.of()); } @@ -66,15 +126,18 @@ public CompleteEvent( Duration duration, int threadId, int processId, - ImmutableMap args) { - this.name = name; - this.category = category; + Map args) { + this.name = name == null ? null : name.intern(); + this.category = category == null ? null : category.intern(); this.start = start; this.duration = duration; this.end = start.plus(duration); this.threadId = threadId; this.processId = processId; - this.args = args; + this.args = + args.entrySet().stream() + .collect( + Collectors.toUnmodifiableMap(e -> e.getKey().intern(), e -> e.getValue().intern())); } @Override diff --git a/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/CounterEvent.java b/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/CounterEvent.java index b935f78..b653b6a 100644 --- a/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/CounterEvent.java +++ b/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/CounterEvent.java @@ -15,25 +15,78 @@ package com.engflow.bazel.invocation.analyzer.traceeventformat; import com.engflow.bazel.invocation.analyzer.time.Timestamp; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import com.google.gson.JsonObject; +import java.util.Arrays; +import java.util.List; +/** + * Counter events can track a value or multiple values as they change over time. + * + * @see specification + */ public class CounterEvent { + @VisibleForTesting + static final List REQUIRED_JSON_MEMBERS = + List.of( + TraceEventFormatConstants.EVENT_NAME, + TraceEventFormatConstants.EVENT_TIMESTAMP, + TraceEventFormatConstants.EVENT_ARGUMENTS); + private final String name; private final Timestamp timestamp; private final double totalValue; - public CounterEvent(JsonObject event) { - this.name = event.get(TraceEventFormatConstants.EVENT_NAME).getAsString().intern(); - this.timestamp = - Timestamp.ofMicros(event.get(TraceEventFormatConstants.EVENT_TIMESTAMP).getAsLong()); + public static CounterEvent fromJson(JsonObject event) { + List missingMembers = Lists.newArrayList(); + for (String requiredMember : REQUIRED_JSON_MEMBERS) { + if (!event.has(requiredMember)) { + missingMembers.add(requiredMember); + } + } + if (!missingMembers.isEmpty()) { + throw new IllegalArgumentException( + "Missing members: " + Arrays.toString(missingMembers.toArray())); + } // For now we are treating all the different counts as a single metric by summing them // together. In the future we may want to respect each count individually. - this.totalValue = + var totalValue = event.get(TraceEventFormatConstants.EVENT_ARGUMENTS).getAsJsonObject().entrySet().stream() .mapToDouble(e -> e.getValue().getAsDouble()) .sum(); + + return new CounterEvent( + event.get(TraceEventFormatConstants.EVENT_NAME).getAsString(), + Timestamp.ofMicros(event.get(TraceEventFormatConstants.EVENT_TIMESTAMP).getAsLong()), + totalValue); + } + + /** + * Parses a {@link CounterEvent} from a JsonObject. + * + * @deprecated Use {@link #fromJson(JsonObject)} instead. + */ + @Deprecated + public CounterEvent(JsonObject event) { + this( + event.get(TraceEventFormatConstants.EVENT_NAME).getAsString(), + Timestamp.ofMicros(event.get(TraceEventFormatConstants.EVENT_TIMESTAMP).getAsLong()), + // For now we are treating all the different counts as a single metric by summing them + // together. In the future we may want to respect each count individually. + event.get(TraceEventFormatConstants.EVENT_ARGUMENTS).getAsJsonObject().entrySet().stream() + .mapToDouble(e -> e.getValue().getAsDouble()) + .sum()); + } + + private CounterEvent(String name, Timestamp timestamp, double totalValue) { + this.name = Preconditions.checkNotNull(name).intern(); + this.timestamp = Preconditions.checkNotNull(timestamp); + this.totalValue = totalValue; } public String getName() { diff --git a/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/InstantEvent.java b/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/InstantEvent.java index 498502c..48a4bee 100644 --- a/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/InstantEvent.java +++ b/analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat/InstantEvent.java @@ -15,19 +15,67 @@ package com.engflow.bazel.invocation.analyzer.traceeventformat; import com.engflow.bazel.invocation.analyzer.time.Timestamp; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import com.google.gson.JsonObject; +import java.util.Arrays; +import java.util.List; +/** + * Instant events describe an event that has no duration. + * + * @see specification + */ public class InstantEvent { + @VisibleForTesting + static final List REQUIRED_JSON_MEMBERS = + List.of( + TraceEventFormatConstants.EVENT_CATEGORY, + TraceEventFormatConstants.EVENT_NAME, + TraceEventFormatConstants.EVENT_TIMESTAMP); + private final String category; private final String name; private final Timestamp timestamp; + public static InstantEvent fromJson(JsonObject event) { + List missingMembers = Lists.newArrayList(); + for (String requiredMember : REQUIRED_JSON_MEMBERS) { + if (!event.has(requiredMember)) { + missingMembers.add(requiredMember); + } + } + if (!missingMembers.isEmpty()) { + throw new IllegalArgumentException( + "Missing members: " + Arrays.toString(missingMembers.toArray())); + } + + return new InstantEvent( + event.get(TraceEventFormatConstants.EVENT_CATEGORY).getAsString(), + event.get(TraceEventFormatConstants.EVENT_NAME).getAsString(), + Timestamp.ofMicros(event.get(TraceEventFormatConstants.EVENT_TIMESTAMP).getAsLong())); + } + + /** + * Parses a {@link InstantEvent} from a JsonObject. + * + * @deprecated Use {@link #fromJson(JsonObject)} instead. + */ + @Deprecated public InstantEvent(JsonObject event) { - this.category = event.get(TraceEventFormatConstants.EVENT_CATEGORY).getAsString().intern(); - this.name = event.get(TraceEventFormatConstants.EVENT_NAME).getAsString().intern(); - this.timestamp = - Timestamp.ofMicros(event.get(TraceEventFormatConstants.EVENT_TIMESTAMP).getAsLong()); + this( + event.get(TraceEventFormatConstants.EVENT_CATEGORY).getAsString(), + event.get(TraceEventFormatConstants.EVENT_NAME).getAsString(), + Timestamp.ofMicros(event.get(TraceEventFormatConstants.EVENT_TIMESTAMP).getAsLong())); + } + + private InstantEvent(String category, String name, Timestamp timestamp) { + this.category = Preconditions.checkNotNull(category).intern(); + this.name = Preconditions.checkNotNull(name).intern(); + this.timestamp = Preconditions.checkNotNull(timestamp); } public String getCategory() { diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/BUILD b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/BUILD new file mode 100644 index 0000000..1a937be --- /dev/null +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/BUILD @@ -0,0 +1,12 @@ +java_test( + name = "traceeventformat", + srcs = glob(["**/*.java"]), + test_class = "com.engflow.bazel.invocation.analyzer.traceeventformat.TraceEventFormatTestSuite", + deps = [ + "//analyzer/java/com/engflow/bazel/invocation/analyzer/time", + "//analyzer/java/com/engflow/bazel/invocation/analyzer/traceeventformat", + "//third_party/gson", + "//third_party/junit", + "//third_party/truth", + ], +) diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/CompleteEventTest.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/CompleteEventTest.java new file mode 100644 index 0000000..67d4463 --- /dev/null +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/CompleteEventTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2024 EngFlow Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.engflow.bazel.invocation.analyzer.traceeventformat; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import com.engflow.bazel.invocation.analyzer.time.TimeUtil; +import com.google.gson.JsonObject; +import org.junit.Test; + +public class CompleteEventTest { + @Test + public void fromJsonThrowsOnMissingMembers() { + var jsonObject = new JsonObject(); + var e = assertThrows(IllegalArgumentException.class, () -> CompleteEvent.fromJson(jsonObject)); + for (var member : CompleteEvent.REQUIRED_JSON_MEMBERS) { + assertThat(e.getMessage()).contains(member); + } + } + + @Test + public void fromJsonMinimal() { + var jsonObject = new JsonObject(); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_TIMESTAMP, 123_456_789); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_DURATION, 456_789); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_THREAD_ID, 42); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_PROCESS_ID, 765); + + var event = CompleteEvent.fromJson(jsonObject); + assertThat(event.name).isNull(); + assertThat(event.category).isNull(); + assertThat(event.start.getMicros()).isEqualTo(123_456_789); + assertThat(TimeUtil.getMicros(event.duration)).isEqualTo(456_789); + assertThat(event.threadId).isEqualTo(42); + assertThat(event.processId).isEqualTo(765); + assertThat(event.args).isEmpty(); + } + + @Test + public void fromJsonAll() { + var jsonObject = new JsonObject(); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_NAME, "fooName"); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_CATEGORY, "fooCat"); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_TIMESTAMP, 123_456_789); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_DURATION, 456_789); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_THREAD_ID, 42); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_PROCESS_ID, 765); + + var args = new JsonObject(); + args.addProperty("argFooKey", "argFooVal"); + args.addProperty("argBarKey", "argBarVal"); + jsonObject.add(TraceEventFormatConstants.EVENT_ARGUMENTS, args); + + var event = CompleteEvent.fromJson(jsonObject); + assertThat(event.name).isEqualTo("fooName"); + assertThat(event.category).isEqualTo("fooCat"); + assertThat(event.start.getMicros()).isEqualTo(123_456_789); + assertThat(TimeUtil.getMicros(event.duration)).isEqualTo(456_789); + assertThat(event.threadId).isEqualTo(42); + assertThat(event.processId).isEqualTo(765); + assertThat(event.args).hasSize(2); + assertThat(event.args).containsEntry("argFooKey", "argFooVal"); + assertThat(event.args).containsEntry("argBarKey", "argBarVal"); + } +} diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/CounterEventTest.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/CounterEventTest.java new file mode 100644 index 0000000..4d1bf0f --- /dev/null +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/CounterEventTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2024 EngFlow Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.engflow.bazel.invocation.analyzer.traceeventformat; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import com.google.gson.JsonObject; +import org.junit.Test; + +public class CounterEventTest { + @Test + public void fromJsonThrowsOnMissingMembers() { + var jsonObject = new JsonObject(); + var e = assertThrows(IllegalArgumentException.class, () -> CounterEvent.fromJson(jsonObject)); + for (var member : CounterEvent.REQUIRED_JSON_MEMBERS) { + assertThat(e.getMessage()).contains(member); + } + } + + @Test + public void fromJson() { + var jsonObject = new JsonObject(); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_NAME, "someEventName"); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_TIMESTAMP, 1_234_567_890); + + var args = new JsonObject(); + args.addProperty("argFooKey", 1.23); + args.addProperty("argBarKey", 3.45); + jsonObject.add(TraceEventFormatConstants.EVENT_ARGUMENTS, args); + + var event = CounterEvent.fromJson(jsonObject); + assertThat(event.getName()).isEqualTo("someEventName"); + assertThat(event.getTimestamp().getMicros()).isEqualTo(1_234_567_890); + assertThat(event.getTotalValue()).isEqualTo(1.23 + 3.45); + } +} diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/InstantEventTest.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/InstantEventTest.java new file mode 100644 index 0000000..0094405 --- /dev/null +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/InstantEventTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2024 EngFlow Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.engflow.bazel.invocation.analyzer.traceeventformat; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; + +import com.google.gson.JsonObject; +import org.junit.Test; + +public class InstantEventTest { + @Test + public void fromJsonThrowsOnMissingMembers() { + var jsonObject = new JsonObject(); + var e = assertThrows(IllegalArgumentException.class, () -> InstantEvent.fromJson(jsonObject)); + for (var member : InstantEvent.REQUIRED_JSON_MEMBERS) { + assertThat(e.getMessage()).contains(member); + } + } + + @Test + public void fromJson() { + var jsonObject = new JsonObject(); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_CATEGORY, "someCategory"); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_NAME, "someEventName"); + jsonObject.addProperty(TraceEventFormatConstants.EVENT_TIMESTAMP, 987_654_321); + + var event = InstantEvent.fromJson(jsonObject); + assertThat(event.getName()).isEqualTo("someEventName"); + assertThat(event.getCategory()).isEqualTo("someCategory"); + assertThat(event.getTimestamp().getMicros()).isEqualTo(987_654_321); + } +} diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/TraceEventFormatTestSuite.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/TraceEventFormatTestSuite.java new file mode 100644 index 0000000..3f321e7 --- /dev/null +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/TraceEventFormatTestSuite.java @@ -0,0 +1,26 @@ +/* + * Copyright 2022 EngFlow Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ + +package com.engflow.bazel.invocation.analyzer.traceeventformat; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + CompleteEventTest.class, + CounterEventTest.class, + InstantEventTest.class, +}) +public class TraceEventFormatTestSuite {} From 82a4655cb8020193ff0dbe84c71b1cf8732b8a3f Mon Sep 17 00:00:00 2001 From: Sara Adams Date: Thu, 23 May 2024 15:25:54 +0200 Subject: [PATCH 2/2] Fix copyright date Signed-off-by: Sara Adams --- .../analyzer/traceeventformat/TraceEventFormatTestSuite.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/TraceEventFormatTestSuite.java b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/TraceEventFormatTestSuite.java index 3f321e7..f381b01 100644 --- a/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/TraceEventFormatTestSuite.java +++ b/analyzer/javatests/com/engflow/bazel/invocation/analyzer/traceeventformat/TraceEventFormatTestSuite.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 EngFlow Inc. + * Copyright 2024 EngFlow Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at