Вынес константы, начал переделаывать тесты
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

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

View File

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

View File

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

View File

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

View File

@ -12,7 +12,6 @@ import test.it.utils.*;
import utils.crypto.Ed25519Util;
import java.time.Duration;
import java.util.Base64;
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
* 2) AddUser(USER2) 200 или 409 USER_ALREADY_EXISTS
* 1) (УБРАНО) AddUser(USER1) создаётся раньше в первом тесте
* 2) (УБРАНО) AddUser(USER2) создаётся раньше в первом тесте
*
* 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) {
int failed = run();
// System.exit(failed);
}
public static int run() {
@ -69,36 +67,9 @@ public class IT_03_AddBlock_NoAuth {
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[] 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)
@ -179,6 +150,7 @@ public class IT_03_AddBlock_NoAuth {
), t);
// 3 EDIT (два сообщения исправляем, одно два раза)
// ВАЖНО: subType EDIT берём из TextBody.SUB_EDIT (единая константа = 10)
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: TEXT#6 (EDIT -> TEXT#2) (исправление #1)");
sender1.send(new TextBody(
TextBody.SUB_EDIT,
@ -281,59 +253,4 @@ public class IT_03_AddBlock_NoAuth {
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();
int failed = runAll();
System.exit(failed);
}
public static int runAll() {