Вынес константы, начал переделаывать тесты
This commit is contained in:
AidarKC 2026-01-08 13:24:55 +03:00
parent f1af2bd4d4
commit e2b89da2fa
7 changed files with 45 additions and 114 deletions

View File

@ -0,0 +1 @@
Сделать возможность убрать свой лайк. (пока не надо а сложность что надо больше проверок)

View File

@ -18,15 +18,15 @@ import java.util.Objects;
* [2] ver=1 * [2] ver=1
* *
* [2] subType (uint16): подтип текстового сообщения * [2] subType (uint16): подтип текстового сообщения
* 1 = новое сообщение (начало ветки) * 1 = новое сообщение (начало ветки)
* 2 = ответ на сообщение (reply) * 2 = ответ на сообщение (reply)
* 3 = репост (repost) * 3 = репост (repost)
* 4 = редактирование (edit) * 10 = редактирование (edit) <-- ВАЖНО: как на сервере/в БД-триггере
* *
* [2] textLenBytes (uint16) длина текста в байтах UTF-8 * [2] textLenBytes (uint16) длина текста в байтах UTF-8
* [N] text UTF-8 * [N] text UTF-8
* *
* Далее ТОЛЬКО если subType == 2 или subType == 3 или subType == 4: * Далее ТОЛЬКО если subType == 2 или subType == 3 или subType == 10:
* [1] toBlockchainNameLen (uint8) * [1] toBlockchainNameLen (uint8)
* [N] toBlockchainName UTF-8 * [N] toBlockchainName UTF-8
* [4] toBlockGlobalNumber (int32) * [4] toBlockGlobalNumber (int32)
@ -46,9 +46,11 @@ public final class TextBody implements BodyRecord, BodyHasTarget {
public static final short SUB_NEW = 1; public static final short SUB_NEW = 1;
public static final short SUB_REPLY = 2; public static final short SUB_REPLY = 2;
public static final short SUB_REPOST = 3; public static final short SUB_REPOST = 3;
public static final short SUB_EDIT = 4;
/** Подтип текстового сообщения (1/2/3/4). */ /** ВАЖНО: EDIT как на сервере (и как ожидает trg_blocks_edit_apply_ai). */
public static final short SUB_EDIT = 10;
/** Подтип текстового сообщения (1/2/3/10). */
public final short subType; public final short subType;
/** Текст сообщения (строго валидный UTF-8, не пустой/не blank). */ /** Текст сообщения (строго валидный UTF-8, не пустой/не blank). */
@ -181,7 +183,7 @@ public final class TextBody implements BodyRecord, BodyHasTarget {
this.toBlockHash32 = null; this.toBlockHash32 = null;
} }
/** Сообщение subType=REPLY (2) или subType=REPOST (3) или subType=EDIT (4) со ссылкой на блок. */ /** Сообщение subType=REPLY (2) или subType=REPOST (3) или subType=EDIT (10) со ссылкой на блок. */
public TextBody(short subType, public TextBody(short subType,
String message, String message,
String toBlockchainName, String toBlockchainName,
@ -303,7 +305,7 @@ public final class TextBody implements BodyRecord, BodyHasTarget {
case SUB_NEW -> "NEW (1)"; case SUB_NEW -> "NEW (1)";
case SUB_REPLY -> "REPLY (2)"; case SUB_REPLY -> "REPLY (2)";
case SUB_REPOST -> "REPOST (3)"; case SUB_REPOST -> "REPOST (3)";
case SUB_EDIT -> "EDIT (4)"; case SUB_EDIT -> "EDIT (10)";
default -> "UNKNOWN"; default -> "UNKNOWN";
}; };

View File

@ -1,6 +1,7 @@
package shine.db; package shine.db;
import utils.config.AppConfig; import utils.config.AppConfig;
import utils.config.MsgSubType;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -185,6 +186,7 @@ public class DatabaseInitializer {
FOREIGN KEY (login) REFERENCES solana_users(login) FOREIGN KEY (login) REFERENCES solana_users(login)
); );
"""); """);
st.executeUpdate(""" st.executeUpdate("""
CREATE INDEX IF NOT EXISTS idx_blockchain_state_login CREATE INDEX IF NOT EXISTS idx_blockchain_state_login
ON blockchain_state (login); ON blockchain_state (login);
@ -271,7 +273,7 @@ public class DatabaseInitializer {
ON connections_state (login, to_login); ON connections_state (login, to_login);
"""); """);
// 8) Trigger: connection state (логика та же) // 8) Trigger: connection state
st.executeUpdate(""" st.executeUpdate("""
CREATE TRIGGER IF NOT EXISTS trg_blocks_connection_state_ai CREATE TRIGGER IF NOT EXISTS trg_blocks_connection_state_ai
AFTER INSERT ON blocks AFTER INSERT ON blocks
@ -288,7 +290,7 @@ public class DatabaseInitializer {
NEW.to_bch_name, NEW.to_bch_name,
NEW.to_block_global_number, NEW.to_block_global_number,
NEW.to_block_hashe NEW.to_block_hashe
WHERE NEW.msg_sub_type IN (10, 20, 30) WHERE NEW.msg_sub_type IN (%d, %d, %d)
AND NEW.to_login IS NOT NULL AND NEW.to_login IS NOT NULL
AND NEW.to_bch_name IS NOT NULL AND NEW.to_bch_name IS NOT NULL
ON CONFLICT(login, rel_type, to_login) ON CONFLICT(login, rel_type, to_login)
@ -301,15 +303,27 @@ public class DatabaseInitializer {
WHERE login = NEW.login WHERE login = NEW.login
AND to_login = NEW.to_login AND to_login = NEW.to_login
AND rel_type = CASE NEW.msg_sub_type AND rel_type = CASE NEW.msg_sub_type
WHEN 11 THEN 10 WHEN %d THEN %d
WHEN 21 THEN 20 WHEN %d THEN %d
WHEN 31 THEN 30 WHEN %d THEN %d
ELSE rel_type ELSE rel_type
END END
AND NEW.msg_sub_type IN (11, 21, 31); AND NEW.msg_sub_type IN (%d, %d, %d);
END; END;
"""); """.formatted(
(int) MsgSubType.CONNECTION_FRIEND,
(int) MsgSubType.CONNECTION_FOLLOW,
(int) MsgSubType.CONNECTION_BLOCK,
(int) MsgSubType.CONNECTION_UNFRIEND, (int) MsgSubType.CONNECTION_FRIEND,
(int) MsgSubType.CONNECTION_UNFOLLOW, (int) MsgSubType.CONNECTION_FOLLOW,
(int) MsgSubType.CONNECTION_UNBLOCK, (int) MsgSubType.CONNECTION_BLOCK,
(int) MsgSubType.CONNECTION_UNFRIEND,
(int) MsgSubType.CONNECTION_UNFOLLOW,
(int) MsgSubType.CONNECTION_UNBLOCK
));
// 9) message_stats (to_block_hash -> BLOB) // 9) message_stats (to_block_hash -> BLOB)
st.executeUpdate(""" st.executeUpdate("""
@ -341,11 +355,11 @@ public class DatabaseInitializer {
ON message_stats (to_login); ON message_stats (to_login);
"""); """);
// 10) Trigger: LIKE (to_block_hashe -> to_block_hash BLOB) // 10) Trigger: LIKE
st.executeUpdate(""" st.executeUpdate("""
CREATE TRIGGER IF NOT EXISTS trg_blocks_message_stats_like_ai CREATE TRIGGER IF NOT EXISTS trg_blocks_message_stats_like_ai
AFTER INSERT ON blocks AFTER INSERT ON blocks
WHEN NEW.msg_type = 2 AND NEW.msg_sub_type = 1 WHEN NEW.msg_type = 2 AND NEW.msg_sub_type = %d
BEGIN BEGIN
INSERT INTO message_stats ( INSERT INTO message_stats (
to_login, to_login,
@ -370,13 +384,13 @@ public class DatabaseInitializer {
DO UPDATE SET DO UPDATE SET
likes_count = message_stats.likes_count + 1; likes_count = message_stats.likes_count + 1;
END; END;
"""); """.formatted((int) MsgSubType.REACTION_LIKE));
// 11) Trigger: REPLY (to_block_hashe -> to_block_hash BLOB) // 11) Trigger: REPLY
st.executeUpdate(""" st.executeUpdate("""
CREATE TRIGGER IF NOT EXISTS trg_blocks_message_stats_reply_ai CREATE TRIGGER IF NOT EXISTS trg_blocks_message_stats_reply_ai
AFTER INSERT ON blocks AFTER INSERT ON blocks
WHEN NEW.msg_type = 1 AND NEW.msg_sub_type = 2 WHEN NEW.msg_type = 1 AND NEW.msg_sub_type = %d
BEGIN BEGIN
INSERT INTO message_stats ( INSERT INTO message_stats (
to_login, to_login,
@ -401,13 +415,13 @@ public class DatabaseInitializer {
DO UPDATE SET DO UPDATE SET
replies_count = message_stats.replies_count + 1; replies_count = message_stats.replies_count + 1;
END; END;
"""); """.formatted((int) MsgSubType.TEXT_REPLY));
// 12) Trigger: EDIT пометить исходный блок // 12) Trigger: EDIT пометить исходный блок
st.executeUpdate(""" st.executeUpdate("""
CREATE TRIGGER IF NOT EXISTS trg_blocks_edit_apply_ai CREATE TRIGGER IF NOT EXISTS trg_blocks_edit_apply_ai
AFTER INSERT ON blocks AFTER INSERT ON blocks
WHEN NEW.msg_type = 1 AND NEW.msg_sub_type = 10 WHEN NEW.msg_type = 1 AND NEW.msg_sub_type = %d
BEGIN BEGIN
UPDATE blocks UPDATE blocks
SET edited_by_block_global_number = NEW.block_global_number SET edited_by_block_global_number = NEW.block_global_number
@ -415,7 +429,7 @@ public class DatabaseInitializer {
AND bch_name = NEW.bch_name AND bch_name = NEW.bch_name
AND block_global_number = NEW.to_block_global_number; AND block_global_number = NEW.to_block_global_number;
END; END;
"""); """.formatted((int) MsgSubType.TEXT_EDIT));
} }
} }
} }

View File

@ -25,7 +25,6 @@ public class IT_01_AddUser {
public static void main(String[] args) { public static void main(String[] args) {
// чтобы тест можно было запускать вообще без JUnit // чтобы тест можно было запускать вообще без JUnit
int failed = run(); int failed = run();
// System.exit(failed);
} }
/** Запуск одного теста (standalone). Возвращает 0 если ок, 1 если упал. */ /** Запуск одного теста (standalone). Возвращает 0 если ок, 1 если упал. */

View File

@ -27,7 +27,6 @@ public class IT_02_Sessions {
public static void main(String[] args) { public static void main(String[] args) {
ItRunContext.initIfNeeded(); ItRunContext.initIfNeeded();
int failed = run(); int failed = run();
System.exit(failed);
} }
/** Запуск одного теста (standalone). Возвращает 0 если ок, 1 если упал. */ /** Запуск одного теста (standalone). Возвращает 0 если ок, 1 если упал. */

View File

@ -12,7 +12,6 @@ import test.it.utils.*;
import utils.crypto.Ed25519Util; import utils.crypto.Ed25519Util;
import java.time.Duration; import java.time.Duration;
import java.util.Base64;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -23,8 +22,8 @@ import static org.junit.jupiter.api.Assertions.*;
* чтобы "четвёртый" сценарий гарантированно запускался сразу после "третьего". * чтобы "четвёртый" сценарий гарантированно запускался сразу после "третьего".
* *
* Сценарий: * Сценарий:
* 1) AddUser(USER1) 200 или 409 USER_ALREADY_EXISTS * 1) (УБРАНО) AddUser(USER1) создаётся раньше в первом тесте
* 2) AddUser(USER2) 200 или 409 USER_ALREADY_EXISTS * 2) (УБРАНО) AddUser(USER2) создаётся раньше в первом тесте
* *
* 3) USER1: HEADER + 3 NEW + 2 REPLY + 2 REACT + 3 EDIT (добавили) * 3) USER1: HEADER + 3 NEW + 2 REPLY + 2 REACT + 3 EDIT (добавили)
* - редактируем два ранее написанных сообщения * - редактируем два ранее написанных сообщения
@ -49,7 +48,6 @@ public class IT_03_AddBlock_NoAuth {
public static void main(String[] args) { public static void main(String[] args) {
int failed = run(); int failed = run();
// System.exit(failed);
} }
public static int run() { public static int run() {
@ -69,36 +67,9 @@ public class IT_03_AddBlock_NoAuth {
Duration t = Duration.ofSeconds(1); Duration t = Duration.ofSeconds(1);
// ========================================================= // =========================================================
// 1) AddUser(USER1) // USER2 keys (детерминированно из login, как твой ItRunContext)
// ========================================================= // =========================================================
addUserOr409AlreadyExists(
"USER1",
TestConfig.LOGIN(),
TestConfig.BCH_NAME(),
TestConfig.LOGIN_PUBKEY_B64(),
TestConfig.DEVICE_PUBKEY_B64()
);
// =========================================================
// 2) AddUser(USER2)
// =========================================================
// Генерим ключи детерминированно из login (как твой ItRunContext)
byte[] user2LoginPriv = Ed25519Util.generatePrivateKeyFromString(USER2_LOGIN); byte[] user2LoginPriv = Ed25519Util.generatePrivateKeyFromString(USER2_LOGIN);
byte[] user2LoginPub = Ed25519Util.derivePublicKey(user2LoginPriv);
byte[] user2DevPriv = Ed25519Util.generatePrivateKeyFromString(USER2_LOGIN + "#device");
byte[] user2DevPub = Ed25519Util.derivePublicKey(user2DevPriv);
String user2LoginPubB64 = Base64.getEncoder().encodeToString(user2LoginPub);
String user2DevPubB64 = Base64.getEncoder().encodeToString(user2DevPub);
addUserOr409AlreadyExists(
"USER2",
USER2_LOGIN,
USER2_BCH,
user2LoginPubB64,
user2DevPubB64
);
// ========================================================= // =========================================================
// 3) USER1 блоки (под message_stats + edits) // 3) USER1 блоки (под message_stats + edits)
@ -179,6 +150,7 @@ public class IT_03_AddBlock_NoAuth {
), t); ), t);
// 3 EDIT (два сообщения исправляем, одно два раза) // 3 EDIT (два сообщения исправляем, одно два раза)
// ВАЖНО: subType EDIT берём из TextBody.SUB_EDIT (единая константа = 10)
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: TEXT#6 (EDIT -> TEXT#2) (исправление #1)"); if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: TEXT#6 (EDIT -> TEXT#2) (исправление #1)");
sender1.send(new TextBody( sender1.send(new TextBody(
TextBody.SUB_EDIT, TextBody.SUB_EDIT,
@ -281,59 +253,4 @@ public class IT_03_AddBlock_NoAuth {
TestLog.pass("IT_03_AddBlock_NoAuth (combined): OK"); TestLog.pass("IT_03_AddBlock_NoAuth (combined): OK");
} }
// ======================================================================
// helpers
// ======================================================================
private static void addUserOr409AlreadyExists(String label,
String login,
String blockchainName,
String loginPubKeyB64,
String devicePubKeyB64) {
TestLog.title(label + ": AddUser (200 OK) или 409 USER_ALREADY_EXISTS");
TestLog.info(" login = " + login);
TestLog.info(" blockchainName = " + blockchainName);
String reqId = "it-adduser-" + label.toLowerCase();
String reqJson = """
{
"op": "AddUser",
"requestId": "%s",
"payload": {
"login": "%s",
"blockchainName": "%s",
"loginKey": "%s",
"deviceKey": "%s",
"bchLimit": %d
}
}
""".formatted(
reqId,
login,
blockchainName,
loginPubKeyB64,
devicePubKeyB64,
TestConfig.TEST_BCH_LIMIT
);
try (WsTestClient client = new WsTestClient(TestConfig.WS_URI)) {
TestLog.send("AddUser(" + label + ")", reqJson);
String resp = client.request(reqId, reqJson, Duration.ofSeconds(5));
TestLog.recv("AddUser(" + label + ")", resp);
int st = JsonParsers.status(resp);
if (st == 200) {
TestLog.ok(label + ": создан/добавлен (status=200)");
} else if (st == 409) {
String code = JsonParsers.errorCode(resp);
assertEquals("USER_ALREADY_EXISTS", code, label + ": expected USER_ALREADY_EXISTS, resp=" + resp);
TestLog.ok(label + ": уже есть (status=409, USER_ALREADY_EXISTS)");
} else {
fail(label + ": неожиданный status=" + st + ", resp=" + resp);
}
}
}
} }

View File

@ -12,7 +12,6 @@ public class IT_RunAllMain {
ItRunContext.initIfNeeded(); ItRunContext.initIfNeeded();
int failed = runAll(); int failed = runAll();
System.exit(failed);
} }
public static int runAll() { public static int runAll() {