08 01 25
Вынес константы, начал переделаывать тесты
This commit is contained in:
parent
f1af2bd4d4
commit
e2b89da2fa
1
DOC/TODO то что пока отложенно на будущее.md
Normal file
1
DOC/TODO то что пока отложенно на будущее.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Сделать возможность убрать свой лайк. (пока не надо а сложность что надо больше проверок)
|
||||||
@ -21,12 +21,12 @@ import java.util.Objects;
|
|||||||
* 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";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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 если упал. */
|
||||||
|
|||||||
@ -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 если упал. */
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -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() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user