This is an automated email from the ASF dual-hosted git repository.

Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 4bec5dff5e test(admin): guard the operation-log audit indexes per 
dialect (#6675) (#7544)
4bec5dff5e is described below

commit 4bec5dff5e632eea287d7e0debb73bd1ab4f1742
Author: wy471x <[email protected]>
AuthorDate: Tue Oct 20 12:39:43 2026 +0800

    test(admin): guard the operation-log audit indexes per dialect (#6675) 
(#7544)
    
    The audit-log screen filters operation_record_log by an operation_time 
range,
    optionally by operator, and always sorts by operation_time desc. Add a 
script
    contract test that asserts both supporting indexes exist in the 
fresh-install
    schema and in the 2.7.1 to 2.7.2 upgrade script of every dialect, so a later
    dialect change cannot silently drop them again.
    
    OceanBase reuses db/init/mysql/schema.sql and openGauss reuses
    db/init/pg/create-table.sql, so the mysql/pg init cases cover them; the 
ob/og
    upgrade cases are still asserted directly. Oracle keeps the shortened
    idx_operation_log_oper_time name because of its 30-character identifier 
limit.
    
    This verifies script content only; it is not an execution test on native
    database engines.
---
 .../mapper/OperationLogIndexContractTest.java      | 132 +++++++++++++++++++++
 1 file changed, 132 insertions(+)

diff --git 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/mapper/OperationLogIndexContractTest.java
 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/mapper/OperationLogIndexContractTest.java
new file mode 100644
index 0000000000..17915b7c28
--- /dev/null
+++ 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/mapper/OperationLogIndexContractTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.shenyu.admin.mapper;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Script contract check for the {@code operation_record_log} audit-log 
indexes.
+ * Every supported dialect must declare both the {@code operation_time} index 
and the
+ * {@code (operator, operation_time)} index that back the time-range and 
per-operator audit-log
+ * queries, in the fresh-install schema as well as the 2.7.1 to 2.7.2 upgrade 
script.
+ * OceanBase reuses the MySQL fresh-install script and openGauss reuses the 
PostgreSQL one, so
+ * those dialects are covered by the {@code mysql} and {@code pg} init cases.
+ * This verifies the scripts only; it is not an execution test on native 
database engines.
+ */
+class OperationLogIndexContractTest {
+
+    private static final String TIME = "operation_time";
+
+    private static final String OPERATOR_TIME = "operator, operation_time";
+
+    /**
+     * The PostgreSQL scripts quote each column, so the normalized column list 
keeps no space
+     * after the comma.
+     */
+    private static final String PG_OPERATOR_TIME = "operator,operation_time";
+
+    /**
+     * Oracle rejects identifiers longer than 30 characters, so the composite 
index uses a
+     * shortened name there; the column list is identical to the other 
dialects.
+     */
+    private static final String ORACLE_OPERATOR_INDEX = 
"idx_operation_log_oper_time";
+
+    @ParameterizedTest(name = "{0} {1}")
+    @MethodSource("scripts")
+    void testOperationLogIndexDeclarations(final String dialect, final String 
kind, final String script,
+                                           final String timeIndex, final 
String operatorIndex) throws IOException {
+        final List<String> statements = 
statementsOf(repositoryRoot().resolve(script));
+        assertTrue(statements.contains(timeIndex), dialect + " " + kind + " is 
missing: " + timeIndex);
+        assertTrue(statements.contains(operatorIndex), dialect + " " + kind + 
" is missing: " + operatorIndex);
+    }
+
+    private static Stream<Arguments> scripts() {
+        return Stream.of(
+                Arguments.of("mysql", "init", "db/init/mysql/schema.sql",
+                        createIndex("idx_operation_log_time", TIME),
+                        createIndex("idx_operation_log_operator_time", 
OPERATOR_TIME)),
+                Arguments.of("pg", "init", "db/init/pg/create-table.sql",
+                        pgIndex("idx_operation_log_time", TIME),
+                        pgIndex("idx_operation_log_operator_time", 
PG_OPERATOR_TIME)),
+                Arguments.of("oracle", "init", "db/init/oracle/schema.sql",
+                        createIndex("idx_operation_log_time", TIME),
+                        createIndex(ORACLE_OPERATOR_INDEX, OPERATOR_TIME)),
+                Arguments.of("mysql", "upgrade", 
"db/upgrade/2.7.1-upgrade-2.7.2-mysql.sql",
+                        createIndex("idx_operation_log_time", TIME),
+                        createIndex("idx_operation_log_operator_time", 
OPERATOR_TIME)),
+                Arguments.of("ob", "upgrade", 
"db/upgrade/2.7.1-upgrade-2.7.2-ob.sql",
+                        alterAddIndex("idx_operation_log_time", TIME),
+                        alterAddIndex("idx_operation_log_operator_time", 
OPERATOR_TIME)),
+                Arguments.of("pg", "upgrade", 
"db/upgrade/2.7.1-upgrade-2.7.2-pg.sql",
+                        pgIndex("idx_operation_log_time", TIME),
+                        pgIndex("idx_operation_log_operator_time", 
PG_OPERATOR_TIME)),
+                Arguments.of("og", "upgrade", 
"db/upgrade/2.7.1-upgrade-2.7.2-og.sql",
+                        pgIndex("idx_operation_log_time", TIME),
+                        pgIndex("idx_operation_log_operator_time", 
PG_OPERATOR_TIME)),
+                Arguments.of("oracle", "upgrade", 
"db/upgrade/2.7.1-upgrade-2.7.2-oracle.sql",
+                        createIndex("idx_operation_log_time", TIME),
+                        createIndex(ORACLE_OPERATOR_INDEX, OPERATOR_TIME)));
+    }
+
+    private static String createIndex(final String name, final String columns) 
{
+        return "create index " + name + " on operation_record_log (" + columns 
+ ")";
+    }
+
+    private static String alterAddIndex(final String name, final String 
columns) {
+        return "alter table operation_record_log add index " + name + " (" + 
columns + ") using btree";
+    }
+
+    private static String pgIndex(final String name, final String columns) {
+        return "create index " + name + " on public.operation_record_log using 
btree (" + columns + ")";
+    }
+
+    private static Path repositoryRoot() {
+        Path root = Paths.get(System.getProperty("user.dir")).toAbsolutePath();
+        while (Objects.nonNull(root) && 
!Files.isDirectory(root.resolve("db/upgrade"))) {
+            root = root.getParent();
+        }
+        assertNotNull(root, "Repository db scripts must be available to the 
test");
+        return root;
+    }
+
+    private static List<String> statementsOf(final Path script) throws 
IOException {
+        final String sql = new String(Files.readAllBytes(script), 
StandardCharsets.UTF_8)
+                .replaceAll("(?m)^\\s*--[^\\r\\n]*", "")
+                .replace("`", "").replace("\"", "").toLowerCase(Locale.ROOT);
+        return Arrays.stream(sql.split(";"))
+                .map(value -> value.trim().replaceAll("\\s+", " "))
+                .collect(Collectors.toList());
+    }
+}

Reply via email to