diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/dao/JDBCBrowserLogQueryDAOTest.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/dao/JDBCBrowserLogQueryDAOTest.java new file mode 100644 index 000000000000..dffae1870552 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/dao/JDBCBrowserLogQueryDAOTest.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao; + +import org.apache.skywalking.oap.server.core.browser.manual.errorlog.BrowserErrorLogRecord; +import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory; +import org.apache.skywalking.oap.server.core.query.input.Duration; +import org.apache.skywalking.oap.server.core.query.enumeration.Step; +import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCClient; +import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.JDBCTableInstaller; +import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.SQLAndParameters; +import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.TableHelper; +import org.joda.time.DateTime; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class JDBCBrowserLogQueryDAOTest { + + private static final String TABLE = BrowserErrorLogRecord.INDEX_NAME; + + @Mock + private JDBCClient jdbcClient; + @Mock + private TableHelper tableHelper; + + private JDBCBrowserLogQueryDAO dao; + + @BeforeEach + void setUp() { + dao = new JDBCBrowserLogQueryDAO(jdbcClient, tableHelper); + } + + @Test + void buildSQL_shouldAlwaysContainTableColumnCondition() { + final SQLAndParameters result = dao.buildSQL(null, null, null, null, null, 10, 0, TABLE); + + assertThat(result.sql()).contains(JDBCTableInstaller.TABLE_COLUMN + " = ?"); + assertThat(result.parameters()).contains(BrowserErrorLogRecord.INDEX_NAME); + } + + @Test + void buildSQL_withNoOptionalConditions_shouldProduceMinimalSQL() { + final SQLAndParameters result = dao.buildSQL(null, null, null, null, null, 10, 0, TABLE); + + assertThat(result.sql()).doesNotContain(BrowserErrorLogRecord.SERVICE_ID); + assertThat(result.sql()).doesNotContain(BrowserErrorLogRecord.SERVICE_VERSION_ID); + assertThat(result.sql()).doesNotContain(BrowserErrorLogRecord.PAGE_PATH_ID); + assertThat(result.sql()).doesNotContain(BrowserErrorLogRecord.ERROR_CATEGORY); + assertThat(result.sql()).doesNotContain(BrowserErrorLogRecord.TIME_BUCKET); + } + + @Test + void buildSQL_withServiceId_shouldIncludeServiceCondition() { + final SQLAndParameters result = dao.buildSQL("service-1", null, null, null, null, 10, 0, TABLE); + + assertThat(result.sql()).contains(BrowserErrorLogRecord.SERVICE_ID + " = ?"); + assertThat(result.parameters()).contains("service-1"); + } + + @Test + void buildSQL_withServiceVersionId_shouldIncludeVersionCondition() { + final SQLAndParameters result = dao.buildSQL(null, "version-1", null, null, null, 10, 0, TABLE); + + assertThat(result.sql()).contains(BrowserErrorLogRecord.SERVICE_VERSION_ID + " = ?"); + assertThat(result.parameters()).contains("version-1"); + } + + @Test + void buildSQL_withPagePathId_shouldIncludePagePathCondition() { + final SQLAndParameters result = dao.buildSQL(null, null, "path-1", null, null, 10, 0, TABLE); + + assertThat(result.sql()).contains(BrowserErrorLogRecord.PAGE_PATH_ID + " = ?"); + assertThat(result.parameters()).contains("path-1"); + } + + @Test + void buildSQL_withCategory_shouldIncludeCategoryCondition() { + final SQLAndParameters result = dao.buildSQL( + null, null, null, BrowserErrorCategory.AJAX, null, 10, 0, TABLE); + + assertThat(result.sql()).contains(BrowserErrorLogRecord.ERROR_CATEGORY + " = ?"); + assertThat(result.parameters()).contains(BrowserErrorCategory.AJAX.getValue()); + } + + @Test + void buildSQL_withDuration_shouldIncludeTimeBucketRange() { + final Duration duration = new Duration(); + duration.setStart(new DateTime(2023, 1, 1, 0, 0).toString("yyyy-MM-dd HHmm")); + duration.setEnd(new DateTime(2023, 1, 2, 0, 0).toString("yyyy-MM-dd HHmm")); + duration.setStep(Step.MINUTE); + + final SQLAndParameters result = dao.buildSQL(null, null, null, null, duration, 10, 0, TABLE); + + assertThat(result.sql()).contains(BrowserErrorLogRecord.TIME_BUCKET + " >= ?"); + assertThat(result.sql()).contains(BrowserErrorLogRecord.TIME_BUCKET + " <= ?"); + } + + @Test + void buildSQL_limitAndOffset_shouldBeApplied() { + final SQLAndParameters result = dao.buildSQL(null, null, null, null, null, 20, 5, TABLE); + + assertThat(result.sql()).contains("limit 25"); + } +} diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/dao/JDBCEventQueryDAOTest.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/dao/JDBCEventQueryDAOTest.java new file mode 100644 index 000000000000..4f4793f96d7e --- /dev/null +++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/dao/JDBCEventQueryDAOTest.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao; + +import io.vavr.Tuple2; +import org.apache.skywalking.oap.server.core.analysis.record.Event; +import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition; +import org.apache.skywalking.oap.server.core.query.type.event.EventType; +import org.apache.skywalking.oap.server.core.query.type.event.Source; +import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCClient; +import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.JDBCTableInstaller; +import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.TableHelper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class JDBCEventQueryDAOTest { + + @Mock + private JDBCClient jdbcClient; + @Mock + private TableHelper tableHelper; + + private JDBCEventQueryDAO dao; + + @BeforeEach + void setUp() { + dao = new JDBCEventQueryDAO(jdbcClient, tableHelper); + } + + @Test + void buildQuery_shouldAlwaysContainTableColumnCondition() { + final EventQueryCondition condition = new EventQueryCondition(); + + final Tuple2, Stream> result = dao.buildQuery(condition); + final List conditions = result._1().collect(Collectors.toList()); + + assertThat(conditions).contains(JDBCTableInstaller.TABLE_COLUMN + " = ?"); + } + + @Test + void buildQuery_withNoOptionalConditions_shouldProduceOnlyTableColumnCondition() { + final EventQueryCondition condition = new EventQueryCondition(); + + final Tuple2, Stream> result = dao.buildQuery(condition); + final List conditions = result._1().collect(Collectors.toList()); + final List parameters = result._2().collect(Collectors.toList()); + + assertThat(conditions).hasSize(1); + assertThat(conditions.get(0)).isEqualTo(JDBCTableInstaller.TABLE_COLUMN + " = ?"); + assertThat(parameters).containsExactly(Event.INDEX_NAME); + } + + @Test + void buildQuery_withUuid_shouldIncludeUuidCondition() { + final EventQueryCondition condition = new EventQueryCondition(); + condition.setUuid("test-uuid"); + + final Tuple2, Stream> result = dao.buildQuery(condition); + final List conditions = result._1().collect(Collectors.toList()); + final List parameters = result._2().collect(Collectors.toList()); + + assertThat(conditions).contains(Event.UUID + "=?"); + assertThat(parameters).contains("test-uuid"); + } + + @Test + void buildQuery_withSource_shouldIncludeServiceConditions() { + final EventQueryCondition condition = new EventQueryCondition(); + final Source source = new Source(); + source.setService("order-service"); + source.setServiceInstance("instance-1"); + source.setEndpoint("/orders"); + condition.setSource(source); + + final Tuple2, Stream> result = dao.buildQuery(condition); + final List conditions = result._1().collect(Collectors.toList()); + final List parameters = result._2().collect(Collectors.toList()); + + assertThat(conditions).contains(Event.SERVICE + "=?"); + assertThat(conditions).contains(Event.SERVICE_INSTANCE + "=?"); + assertThat(conditions).contains(Event.ENDPOINT + "=?"); + assertThat(parameters).contains("order-service", "instance-1", "/orders"); + } + + @Test + void buildQuery_withEventType_shouldIncludeTypeCondition() { + final EventQueryCondition condition = new EventQueryCondition(); + condition.setType(EventType.Normal); + + final Tuple2, Stream> result = dao.buildQuery(condition); + final List conditions = result._1().collect(Collectors.toList()); + final List parameters = result._2().collect(Collectors.toList()); + + assertThat(conditions).contains(Event.TYPE + "=?"); + assertThat(parameters).contains(EventType.Normal.name()); + } + + @Test + void buildQuery_withTableColumnConditionOnlyOnce() { + final EventQueryCondition condition = new EventQueryCondition(); + condition.setUuid("uuid-1"); + + final Tuple2, Stream> result = dao.buildQuery(condition); + final List conditions = result._1().collect(Collectors.toList()); + + final long tableColumnCount = conditions.stream() + .filter(c -> c.equals(JDBCTableInstaller.TABLE_COLUMN + " = ?")) + .count(); + assertThat(tableColumnCount).as("TABLE_COLUMN condition should appear exactly once").isEqualTo(1); + } +} diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/dao/JDBCProfileThreadSnapshotQueryDAOTest.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/dao/JDBCProfileThreadSnapshotQueryDAOTest.java new file mode 100644 index 000000000000..808d2e4a17a9 --- /dev/null +++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/common/dao/JDBCProfileThreadSnapshotQueryDAOTest.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.oap.server.storage.plugin.jdbc.common.dao; + +import org.apache.skywalking.oap.server.core.profiling.trace.ProfileThreadSnapshotRecord; +import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCClient; +import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.JDBCTableInstaller; +import org.apache.skywalking.oap.server.storage.plugin.jdbc.common.TableHelper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicReference; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doAnswer; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +class JDBCProfileThreadSnapshotQueryDAOTest { + + private static final String TABLE = ProfileThreadSnapshotRecord.INDEX_NAME; + + @Mock + private JDBCClient jdbcClient; + @Mock + private TableHelper tableHelper; + + private JDBCProfileThreadSnapshotQueryDAO dao; + + @BeforeEach + void setUp() { + dao = new JDBCProfileThreadSnapshotQueryDAO(jdbcClient, tableHelper); + } + + @Test + void querySegments_shouldContainTableColumnCondition() throws SQLException { + final AtomicReference capturedSql = new AtomicReference<>(); + doAnswer(invocation -> { + capturedSql.set(invocation.getArgument(0)); + return new ArrayList<>(); + }).when(jdbcClient).executeQuery(anyString(), any(), any(Object[].class)); + + dao.querySegments("task-1", TABLE); + + assertThat(capturedSql.get()).contains(JDBCTableInstaller.TABLE_COLUMN + " = ?"); + } + + @Test + void querySegments_shouldFilterByTaskId() throws SQLException { + final AtomicReference capturedSql = new AtomicReference<>(); + doAnswer(invocation -> { + capturedSql.set(invocation.getArgument(0)); + return new ArrayList<>(); + }).when(jdbcClient).executeQuery(anyString(), any(), any(Object[].class)); + + dao.querySegments("task-abc", TABLE); + + assertThat(capturedSql.get()).contains(ProfileThreadSnapshotRecord.TASK_ID + " = ?"); + } + + @Test + void querySegments_shouldFilterBySequenceZero() throws SQLException { + final AtomicReference capturedSql = new AtomicReference<>(); + doAnswer(invocation -> { + capturedSql.set(invocation.getArgument(0)); + return new ArrayList<>(); + }).when(jdbcClient).executeQuery(anyString(), any(), any(Object[].class)); + + dao.querySegments("task-1", TABLE); + + assertThat(capturedSql.get()).contains(ProfileThreadSnapshotRecord.SEQUENCE + " = 0"); + } +}