02 01 25
ОГО доделал и тесты (теперь два пользователя добавляется и меж ними есть связи) вроде всё работает
This commit is contained in:
parent
c3d20ba338
commit
432b574592
@ -1,32 +1,49 @@
|
|||||||
package test.it;
|
package test.it;
|
||||||
|
|
||||||
|
import blockchain.body.ConnectionBody;
|
||||||
import blockchain.body.HeaderBody;
|
import blockchain.body.HeaderBody;
|
||||||
import blockchain.body.ReactionBody;
|
import blockchain.body.ReactionBody;
|
||||||
import blockchain.body.TextBody;
|
import blockchain.body.TextBody;
|
||||||
|
import blockchain.body.UserParamBody;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import test.it.addBlockUtils.AddBlockSender;
|
import test.it.addBlockUtils.AddBlockSender;
|
||||||
import test.it.addBlockUtils.ChainState;
|
import test.it.addBlockUtils.ChainState;
|
||||||
import test.it.utils.ItRunContext;
|
import test.it.utils.*;
|
||||||
import test.it.utils.TestConfig;
|
import utils.crypto.Ed25519Util;
|
||||||
import test.it.utils.TestLog;
|
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
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.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IT_03_AddBlock_NoAuth
|
* IT_03_AddBlock_NoAuth
|
||||||
*
|
*
|
||||||
* Теперь тест максимально "линейный":
|
* ОБЪЕДИНЕНО: прежний IT_03 + прежний IT_04 в одном тесте,
|
||||||
* - создаём только Body
|
* чтобы "четвёртый" сценарий гарантированно запускался сразу после "третьего".
|
||||||
* - sender.send(body) делает всё остальное (номера, prev-hash, подпись, отправка, проверка, state)
|
|
||||||
*
|
*
|
||||||
* ДОБАВЛЕНО:
|
* Сценарий:
|
||||||
* - 2 reply на старые сообщения (включая reply на reply)
|
* 1) AddUser(USER1) 200 или 409 USER_ALREADY_EXISTS
|
||||||
* - ещё 1 реакция (вторая)
|
* 2) AddUser(USER2) 200 или 409 USER_ALREADY_EXISTS
|
||||||
|
*
|
||||||
|
* 3) USER1: HEADER + 3 NEW + 2 REPLY + 2 REACT (как было)
|
||||||
|
* 4) USER2: HEADER + UserParams(name+address) + Connection(FRIEND -> USER1)
|
||||||
|
* 5) USER1: UserParams(name+surname) + Connection(FRIEND -> USER2) + Connection(FOLLOW -> USER2)
|
||||||
|
*
|
||||||
|
* Важно:
|
||||||
|
* - у каждого пользователя СВОЙ ChainState
|
||||||
|
* - AddBlockSender создаём с новой сигнатурой:
|
||||||
|
* new AddBlockSender(state, login, blockchainName, loginPrivKey)
|
||||||
|
* - USER2 ключи делаем детерминированно из login (как в ItRunContext), но локально.
|
||||||
*/
|
*/
|
||||||
public class IT_03_AddBlock_NoAuth {
|
public class IT_03_AddBlock_NoAuth {
|
||||||
|
|
||||||
|
// ===== USER2 (константы прямо тут, чтобы не ломать твой TestConfig) =====
|
||||||
|
private static final String USER2_LOGIN = "Anya2";
|
||||||
|
private static final String BCH_SUFFIX_3 = "001";
|
||||||
|
private static final String USER2_BCH = USER2_LOGIN + BCH_SUFFIX_3;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
int failed = run();
|
int failed = run();
|
||||||
// System.exit(failed);
|
// System.exit(failed);
|
||||||
@ -39,7 +56,7 @@ public class IT_03_AddBlock_NoAuth {
|
|||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void ensureUserExists() {
|
static void ensureUserExists() {
|
||||||
ItRunContext.initIfNeeded();
|
ItRunContext.initIfNeeded();
|
||||||
// как и было: предусловие можно включить потом
|
// можно оставить пустым, как у тебя
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testBody() {
|
private static void testBody() {
|
||||||
@ -48,51 +65,79 @@ public class IT_03_AddBlock_NoAuth {
|
|||||||
|
|
||||||
Duration t = Duration.ofSeconds(1);
|
Duration t = Duration.ofSeconds(1);
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// 1) AddUser(USER1)
|
||||||
|
// =========================================================
|
||||||
|
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 блоки (как было раньше в IT_03)
|
||||||
|
// =========================================================
|
||||||
if (TestConfig.DEBUG()) {
|
if (TestConfig.DEBUG()) {
|
||||||
TestLog.titleBlock("""
|
TestLog.titleBlock("""
|
||||||
IT_03_AddBlock_NoAuth: AddBlock без отдельной авторизации (Body-only в тесте)
|
IT_03_AddBlock_NoAuth (combined): USER1 + USER2 сценарии
|
||||||
login = %s
|
USER1 login = %s
|
||||||
blockchainName = %s
|
USER1 blockchainName= %s
|
||||||
""".formatted(TestConfig.LOGIN(), TestConfig.BCH_NAME()));
|
USER2 login = %s
|
||||||
|
USER2 blockchainName= %s
|
||||||
|
""".formatted(TestConfig.LOGIN(), TestConfig.BCH_NAME(), USER2_LOGIN, USER2_BCH));
|
||||||
}
|
}
|
||||||
|
|
||||||
ChainState state = new ChainState();
|
ChainState st1 = new ChainState();
|
||||||
AddBlockSender sender = new AddBlockSender(state);
|
AddBlockSender sender1 = new AddBlockSender(
|
||||||
|
st1,
|
||||||
|
TestConfig.LOGIN(),
|
||||||
|
TestConfig.BCH_NAME(),
|
||||||
|
TestConfig.LOGIN_PRIV_KEY()
|
||||||
|
);
|
||||||
|
|
||||||
// =========================================================
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: HEADER");
|
||||||
// 0) HEADER
|
sender1.send(new HeaderBody(TestConfig.LOGIN()), t);
|
||||||
// =========================================================
|
assertTrue(st1.hasHeader());
|
||||||
if (TestConfig.DEBUG()) TestLog.stepTitle("ШАГ 0: HEADER");
|
|
||||||
sender.send(new HeaderBody(TestConfig.LOGIN()), t);
|
|
||||||
assertTrue(state.hasHeader());
|
|
||||||
|
|
||||||
// =========================================================
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: TEXT#1 (NEW)");
|
||||||
// 1..3) TEXT NEW
|
sender1.send(new TextBody(TextBody.SUB_NEW, "Hello #1 (NEW) from IT_03 test"), t);
|
||||||
// =========================================================
|
|
||||||
if (TestConfig.DEBUG()) TestLog.stepTitle("ШАГ 1: TEXT#1 (NEW)");
|
|
||||||
sender.send(new TextBody(TextBody.SUB_NEW, "Hello #1 (NEW) from IT_03 test"), t);
|
|
||||||
|
|
||||||
if (TestConfig.DEBUG()) TestLog.stepTitle("ШАГ 2: TEXT#2 (NEW)");
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: TEXT#2 (NEW)");
|
||||||
sender.send(new TextBody(TextBody.SUB_NEW, "Hello #2 (NEW) from IT_03 test"), t);
|
sender1.send(new TextBody(TextBody.SUB_NEW, "Hello #2 (NEW) from IT_03 test"), t);
|
||||||
|
|
||||||
if (TestConfig.DEBUG()) TestLog.stepTitle("ШАГ 3: TEXT#3 (NEW)");
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: TEXT#3 (NEW)");
|
||||||
sender.send(new TextBody(TextBody.SUB_NEW, "Hello #3 (NEW) from IT_03 test"), t);
|
sender1.send(new TextBody(TextBody.SUB_NEW, "Hello #3 (NEW) from IT_03 test"), t);
|
||||||
|
|
||||||
// Теперь у нас есть:
|
byte[] text1Hash = st1.getGlobalHash32(1);
|
||||||
// global=1 -> TEXT#1
|
byte[] text2Hash = st1.getGlobalHash32(2);
|
||||||
// global=2 -> TEXT#2
|
|
||||||
// global=3 -> TEXT#3
|
|
||||||
|
|
||||||
byte[] text1Hash = state.getGlobalHash32(1);
|
|
||||||
byte[] text2Hash = state.getGlobalHash32(2);
|
|
||||||
assertNotNull(text1Hash);
|
assertNotNull(text1Hash);
|
||||||
assertNotNull(text2Hash);
|
assertNotNull(text2Hash);
|
||||||
|
|
||||||
// =========================================================
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: TEXT#4 (REPLY -> TEXT#1)");
|
||||||
// 4) REPLY на TEXT#1
|
sender1.send(new TextBody(
|
||||||
// =========================================================
|
|
||||||
if (TestConfig.DEBUG()) TestLog.stepTitle("ШАГ 4: TEXT#4 (REPLY -> TEXT#1)");
|
|
||||||
sender.send(new TextBody(
|
|
||||||
TextBody.SUB_REPLY,
|
TextBody.SUB_REPLY,
|
||||||
"Reply to TEXT#1",
|
"Reply to TEXT#1",
|
||||||
TestConfig.BCH_NAME(),
|
TestConfig.BCH_NAME(),
|
||||||
@ -100,15 +145,11 @@ public class IT_03_AddBlock_NoAuth {
|
|||||||
text1Hash
|
text1Hash
|
||||||
), t);
|
), t);
|
||||||
|
|
||||||
// global=4 -> REPLY на global=1
|
byte[] reply1Hash = st1.getGlobalHash32(4);
|
||||||
byte[] reply1Hash = state.getGlobalHash32(4);
|
|
||||||
assertNotNull(reply1Hash);
|
assertNotNull(reply1Hash);
|
||||||
|
|
||||||
// =========================================================
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: TEXT#5 (REPLY -> TEXT#4)");
|
||||||
// 5) REPLY на REPLY (ответ на ответ)
|
sender1.send(new TextBody(
|
||||||
// =========================================================
|
|
||||||
if (TestConfig.DEBUG()) TestLog.stepTitle("ШАГ 5: TEXT#5 (REPLY -> TEXT#4)");
|
|
||||||
sender.send(new TextBody(
|
|
||||||
TextBody.SUB_REPLY,
|
TextBody.SUB_REPLY,
|
||||||
"Reply to REPLY (TEXT#4)",
|
"Reply to REPLY (TEXT#4)",
|
||||||
TestConfig.BCH_NAME(),
|
TestConfig.BCH_NAME(),
|
||||||
@ -116,39 +157,140 @@ public class IT_03_AddBlock_NoAuth {
|
|||||||
reply1Hash
|
reply1Hash
|
||||||
), t);
|
), t);
|
||||||
|
|
||||||
// =========================================================
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: REACT#1 (LIKE -> TEXT#1)");
|
||||||
// 6) REACTION#1 -> LIKE на TEXT#1
|
sender1.send(new ReactionBody(
|
||||||
// =========================================================
|
|
||||||
if (TestConfig.DEBUG()) TestLog.stepTitle("ШАГ 6: REACT#1 (LIKE -> TEXT#1)");
|
|
||||||
sender.send(new ReactionBody(
|
|
||||||
ReactionBody.SUB_LIKE,
|
ReactionBody.SUB_LIKE,
|
||||||
TestConfig.BCH_NAME(),
|
TestConfig.BCH_NAME(),
|
||||||
1,
|
1,
|
||||||
text1Hash
|
text1Hash
|
||||||
), t);
|
), t);
|
||||||
|
|
||||||
// =========================================================
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: REACT#2 (LIKE -> TEXT#4)");
|
||||||
// 7) REACTION#2 -> LIKE на REPLY (TEXT#4)
|
sender1.send(new ReactionBody(
|
||||||
// =========================================================
|
|
||||||
if (TestConfig.DEBUG()) TestLog.stepTitle("ШАГ 7: REACT#2 (LIKE -> TEXT#4)");
|
|
||||||
sender.send(new ReactionBody(
|
|
||||||
ReactionBody.SUB_LIKE,
|
ReactionBody.SUB_LIKE,
|
||||||
TestConfig.BCH_NAME(),
|
TestConfig.BCH_NAME(),
|
||||||
4,
|
4,
|
||||||
reply1Hash
|
reply1Hash
|
||||||
), t);
|
), t);
|
||||||
|
|
||||||
// =========================================================
|
assertEquals(7, st1.globalLastNumber(), "USER1: должно быть 8 блоков: globalLastNumber=7");
|
||||||
// Итоги: 1 header + 3 new + 2 reply + 2 react = 8 блоков
|
assertEquals(5, st1.lineLastNumber((short) 1), "USER1: line=1 должно быть 5 TEXT блоков (3 new + 2 reply)");
|
||||||
// globalLastNumber должен быть 7
|
assertEquals(2, st1.lineLastNumber((short) 2), "USER1: line=2 должно быть 2 REACTION блока");
|
||||||
// =========================================================
|
|
||||||
assertEquals(7, state.globalLastNumber(), "Должно быть 8 блоков: globalLastNumber=7");
|
|
||||||
assertEquals(5, state.lineLastNumber((short) 1), "В line=1 должно быть 5 TEXT блоков (3 new + 2 reply)");
|
|
||||||
assertEquals(2, state.lineLastNumber((short) 2), "В line=2 должно быть 2 REACTION блока");
|
|
||||||
|
|
||||||
assertNotNull(state.globalLastHashHex());
|
// =========================================================
|
||||||
assertEquals(64, state.globalLastHashHex().length());
|
// 4) USER2: HEADER + PARAMS + FRIEND->USER1
|
||||||
|
// =========================================================
|
||||||
|
ChainState st2 = new ChainState();
|
||||||
|
AddBlockSender sender2 = new AddBlockSender(
|
||||||
|
st2,
|
||||||
|
USER2_LOGIN,
|
||||||
|
USER2_BCH,
|
||||||
|
user2LoginPriv
|
||||||
|
);
|
||||||
|
|
||||||
TestLog.pass("IT_03_AddBlock_NoAuth: OK");
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER2: HEADER");
|
||||||
|
sender2.send(new HeaderBody(USER2_LOGIN), t);
|
||||||
|
assertTrue(st2.hasHeader());
|
||||||
|
|
||||||
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER2: UserParams (name + address)");
|
||||||
|
sender2.send(new UserParamBody(
|
||||||
|
"Anya",
|
||||||
|
"Amsterdam, Example street 10"
|
||||||
|
), t);
|
||||||
|
|
||||||
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER2: Connection (FRIEND -> USER1)");
|
||||||
|
sender2.send(new ConnectionBody(
|
||||||
|
ConnectionBody.SUB_FRIEND,
|
||||||
|
TestConfig.LOGIN(), // to_login (USER1)
|
||||||
|
TestConfig.BCH_NAME(), // toBch (USER1 chain)
|
||||||
|
0,
|
||||||
|
new byte[32]
|
||||||
|
), t);
|
||||||
|
|
||||||
|
// =========================================================
|
||||||
|
// 5) USER1: params + взаимность + подписка (без нового HEADER!)
|
||||||
|
// =========================================================
|
||||||
|
// ВАЖНО: мы НЕ создаём новый ChainState для USER1, и НЕ шлём header заново.
|
||||||
|
// Мы продолжаем тем же sender1 и st1, иначе будет пытаться начать цепочку заново.
|
||||||
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: UserParams (name + surname)");
|
||||||
|
sender1.send(new UserParamBody(
|
||||||
|
"Anna",
|
||||||
|
"Gareeva"
|
||||||
|
), t);
|
||||||
|
|
||||||
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: Connection (FRIEND -> USER2)");
|
||||||
|
sender1.send(new ConnectionBody(
|
||||||
|
ConnectionBody.SUB_FRIEND,
|
||||||
|
USER2_LOGIN,
|
||||||
|
USER2_BCH,
|
||||||
|
0,
|
||||||
|
new byte[32]
|
||||||
|
), t);
|
||||||
|
|
||||||
|
if (TestConfig.DEBUG()) TestLog.stepTitle("USER1: Connection (FOLLOW -> USER2)");
|
||||||
|
sender1.send(new ConnectionBody(
|
||||||
|
ConnectionBody.SUB_FOLLOW,
|
||||||
|
USER2_LOGIN,
|
||||||
|
USER2_BCH,
|
||||||
|
0,
|
||||||
|
new byte[32]
|
||||||
|
), t);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5,19 +5,6 @@ import test.it.utils.TestLog;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Ручной запуск всех IT тестов БЕЗ JUnit / Suite.
|
* Ручной запуск всех IT тестов БЕЗ JUnit / Suite.
|
||||||
*
|
|
||||||
* Делает:
|
|
||||||
* 1) запускает тесты по очереди
|
|
||||||
* 2) печатает итоговый короткий отчёт
|
|
||||||
*
|
|
||||||
* Запуск из IDE:
|
|
||||||
* Run 'main' этого класса
|
|
||||||
*
|
|
||||||
* Запуск из консоли:
|
|
||||||
* ./gradlew testClasses
|
|
||||||
* java -cp ... test.it.IT_RunAllMain
|
|
||||||
*
|
|
||||||
* (Classpath зависит от твоего Gradle, но в IDE проще всего)
|
|
||||||
*/
|
*/
|
||||||
public class IT_RunAllMain {
|
public class IT_RunAllMain {
|
||||||
|
|
||||||
@ -25,15 +12,9 @@ public class IT_RunAllMain {
|
|||||||
ItRunContext.initIfNeeded();
|
ItRunContext.initIfNeeded();
|
||||||
|
|
||||||
int failed = runAll();
|
int failed = runAll();
|
||||||
|
|
||||||
// Удобно для CI: код выхода = число упавших тестов
|
|
||||||
System.exit(failed);
|
System.exit(failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Основной метод, который возвращает число не пройденных тестов (0 если всё хорошо).
|
|
||||||
* Его можно вызывать из других раннеров (например, из варианта с очисткой data/).
|
|
||||||
*/
|
|
||||||
public static int runAll() {
|
public static int runAll() {
|
||||||
|
|
||||||
final int total = 3;
|
final int total = 3;
|
||||||
@ -42,23 +23,18 @@ public class IT_RunAllMain {
|
|||||||
|
|
||||||
TestLog.title("IT RUN: запуск всех тестов подряд (без очистки data/)");
|
TestLog.title("IT RUN: запуск всех тестов подряд (без очистки data/)");
|
||||||
|
|
||||||
// 1) IT_01_AddUser
|
|
||||||
TestLog.stepTitle("RUN: IT_01_AddUser");
|
TestLog.stepTitle("RUN: IT_01_AddUser");
|
||||||
int f1 = IT_01_AddUser.run();
|
int f1 = IT_01_AddUser.run();
|
||||||
failed += f1; passed += (f1 == 0 ? 1 : 0);
|
failed += f1; passed += (f1 == 0 ? 1 : 0);
|
||||||
|
|
||||||
// 2) IT_02_Sessions
|
|
||||||
TestLog.stepTitle("RUN: IT_02_Sessions");
|
TestLog.stepTitle("RUN: IT_02_Sessions");
|
||||||
int f2 = IT_02_Sessions.run();
|
int f2 = IT_02_Sessions.run();
|
||||||
failed += f2; passed += (f2 == 0 ? 1 : 0);
|
failed += f2; passed += (f2 == 0 ? 1 : 0);
|
||||||
|
|
||||||
// 3) IT_03_AddBlock_NoAuth (оставлен как есть, поэтому запускаем через его main)
|
TestLog.stepTitle("RUN: IT_03_AddBlock_NoAuth (combined 3+4)");
|
||||||
// Если он упадёт — он кинет исключение. Мы перехватим и посчитаем как fail=1.
|
|
||||||
TestLog.stepTitle("RUN: IT_03_AddBlock_NoAuth (main)");
|
|
||||||
int f3 = IT_03_AddBlock_NoAuth.run();
|
int f3 = IT_03_AddBlock_NoAuth.run();
|
||||||
failed += f3; passed += (f3 == 0 ? 1 : 0);
|
failed += f3; passed += (f3 == 0 ? 1 : 0);
|
||||||
|
|
||||||
// Итоговый короткий отчёт
|
|
||||||
TestLog.titleBlock("""
|
TestLog.titleBlock("""
|
||||||
IT RUN RESULT
|
IT RUN RESULT
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|||||||
@ -3,9 +3,7 @@ package test.it.addBlockUtils;
|
|||||||
import blockchain.BchBlockEntry;
|
import blockchain.BchBlockEntry;
|
||||||
import blockchain.BchCryptoVerifier;
|
import blockchain.BchCryptoVerifier;
|
||||||
import blockchain.body.BodyRecord;
|
import blockchain.body.BodyRecord;
|
||||||
import test.it.utils.TestConfig;
|
|
||||||
import test.it.utils.TestLog;
|
import test.it.utils.TestLog;
|
||||||
import utils.crypto.Ed25519Util;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
@ -17,7 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* AddBlockSender — "одна кнопка":
|
* AddBlockSender — "одна кнопка":
|
||||||
* - принимает ГОТОВЫЙ Body (HeaderBody/TextBody/ReactionBody)
|
* - принимает ГОТОВЫЙ Body (HeaderBody/TextBody/ReactionBody/ConnectionBody/UserParamsBody и т.п.)
|
||||||
* - сам берёт номера/prev-hash из ChainState
|
* - сам берёт номера/prev-hash из ChainState
|
||||||
* - строит raw/hash/signature
|
* - строит raw/hash/signature
|
||||||
* - собирает BchBlockEntry (старый, без изменений)
|
* - собирает BchBlockEntry (старый, без изменений)
|
||||||
@ -25,8 +23,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||||||
* - проверяет serverLastGlobalHash == localHash
|
* - проверяет serverLastGlobalHash == localHash
|
||||||
* - обновляет ChainState
|
* - обновляет ChainState
|
||||||
*
|
*
|
||||||
* В тестах:
|
* ИЗМЕНЕНО:
|
||||||
* sender.send(body, timeout);
|
* - sender больше НЕ завязан на TestConfig.LOGIN()/BCH_NAME()/ключи
|
||||||
|
* - теперь он работает от параметров конкретного пользователя:
|
||||||
|
* login, blockchainName, loginPrivKey
|
||||||
*/
|
*/
|
||||||
public final class AddBlockSender {
|
public final class AddBlockSender {
|
||||||
|
|
||||||
@ -35,17 +35,22 @@ public final class AddBlockSender {
|
|||||||
|
|
||||||
private final ChainState state;
|
private final ChainState state;
|
||||||
|
|
||||||
public AddBlockSender(ChainState state) {
|
private final String login;
|
||||||
|
private final String blockchainName;
|
||||||
|
private final byte[] loginPrivKey;
|
||||||
|
|
||||||
|
public AddBlockSender(ChainState state, String login, String blockchainName, byte[] loginPrivKey) {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
|
this.login = login;
|
||||||
|
this.blockchainName = blockchainName;
|
||||||
|
this.loginPrivKey = (loginPrivKey == null ? null : loginPrivKey.clone());
|
||||||
|
if (this.loginPrivKey == null) throw new IllegalArgumentException("loginPrivKey == null");
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChainState state() {
|
public ChainState state() { return state; }
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Отправить следующий блок по body.expectedLineIndex().
|
* Отправить следующий блок по body.expectedLineIndex().
|
||||||
* Ничего не возвращает — состояние хранится в ChainState.
|
|
||||||
*/
|
*/
|
||||||
public void send(BodyRecord body, Duration timeout) {
|
public void send(BodyRecord body, Duration timeout) {
|
||||||
if (body == null) throw new IllegalArgumentException("body == null");
|
if (body == null) throw new IllegalArgumentException("body == null");
|
||||||
@ -70,10 +75,9 @@ public final class AddBlockSender {
|
|||||||
byte[] prevLineHash32 = (lineIndex == 0) ? ZERO32 : state.prevLineHash32ForNext(lineIndex);
|
byte[] prevLineHash32 = (lineIndex == 0) ? ZERO32 : state.prevLineHash32ForNext(lineIndex);
|
||||||
|
|
||||||
long ts = System.currentTimeMillis() / 1000L;
|
long ts = System.currentTimeMillis() / 1000L;
|
||||||
|
|
||||||
byte[] bodyBytes = body.toBytes();
|
byte[] bodyBytes = body.toBytes();
|
||||||
|
|
||||||
// RAW bytes (ровно то, что подписываем/хэшируем)
|
// RAW bytes
|
||||||
int recordSize = BchBlockEntry.RAW_HEADER_SIZE + bodyBytes.length;
|
int recordSize = BchBlockEntry.RAW_HEADER_SIZE + bodyBytes.length;
|
||||||
|
|
||||||
byte[] rawBytes = ByteBuffer.allocate(recordSize)
|
byte[] rawBytes = ByteBuffer.allocate(recordSize)
|
||||||
@ -88,13 +92,13 @@ public final class AddBlockSender {
|
|||||||
|
|
||||||
// preimage -> sha256 -> signature
|
// preimage -> sha256 -> signature
|
||||||
byte[] preimage = BchCryptoVerifier.buildPreimage(
|
byte[] preimage = BchCryptoVerifier.buildPreimage(
|
||||||
TestConfig.LOGIN(),
|
login,
|
||||||
prevGlobalHash32,
|
prevGlobalHash32,
|
||||||
prevLineHash32,
|
prevLineHash32,
|
||||||
rawBytes
|
rawBytes
|
||||||
);
|
);
|
||||||
byte[] hash32 = BchCryptoVerifier.sha256(preimage);
|
byte[] hash32 = BchCryptoVerifier.sha256(preimage);
|
||||||
byte[] signature64 = Ed25519Util.sign(hash32, TestConfig.LOGIN_PRIV_KEY());
|
byte[] signature64 = utils.crypto.Ed25519Util.sign(hash32, loginPrivKey);
|
||||||
|
|
||||||
// Собираем полный блок (BchBlockEntry не меняем)
|
// Собираем полный блок (BchBlockEntry не меняем)
|
||||||
BchBlockEntry entry = new BchBlockEntry(
|
BchBlockEntry entry = new BchBlockEntry(
|
||||||
@ -107,28 +111,30 @@ public final class AddBlockSender {
|
|||||||
hash32
|
hash32
|
||||||
);
|
);
|
||||||
|
|
||||||
// отправляем JSON
|
// JSON AddBlock
|
||||||
String prevGlobalHashHex = (globalNumber == 0) ? ZERO64 : state.globalLastHashHex();
|
String prevGlobalHashHex = (globalNumber == 0) ? ZERO64 : state.globalLastHashHex();
|
||||||
|
|
||||||
String req = buildAddBlockJson(
|
String req = buildAddBlockJson(
|
||||||
TestConfig.BCH_NAME(),
|
blockchainName,
|
||||||
globalNumber,
|
globalNumber,
|
||||||
prevGlobalHashHex,
|
prevGlobalHashHex,
|
||||||
base64(entry.toBytes())
|
base64(entry.toBytes())
|
||||||
);
|
);
|
||||||
|
|
||||||
String op = "AddBlock (global=" + globalNumber + ", line=" + lineIndex + ", lineNum=" + lineNumber + ")";
|
String op = "AddBlock (user=" + login + ", bch=" + blockchainName +
|
||||||
|
", global=" + globalNumber + ", line=" + lineIndex + ", lineNum=" + lineNumber + ")";
|
||||||
|
|
||||||
String resp = WsJsonOneShot.request(op, req, timeout);
|
String resp = WsJsonOneShot.request(op, req, timeout);
|
||||||
|
|
||||||
assert200(op, resp);
|
assert200(op, resp);
|
||||||
|
|
||||||
String serverLastGlobalHash = extractPayloadString(resp, "serverLastGlobalHash");
|
String serverLastGlobalHash = JsonMini.extractPayloadString(resp, "serverLastGlobalHash");
|
||||||
assertNotNull(serverLastGlobalHash, op + ": payload.serverLastGlobalHash must not be null");
|
assertNotNull(serverLastGlobalHash, op + ": payload.serverLastGlobalHash must not be null");
|
||||||
assertEquals(64, serverLastGlobalHash.trim().length(), op + ": serverLastGlobalHash must be 64 hex chars");
|
assertEquals(64, serverLastGlobalHash.trim().length(), op + ": serverLastGlobalHash must be 64 hex chars");
|
||||||
|
|
||||||
String localHashHex = bytesToHex64(hash32);
|
String localHashHex = bytesToHex64(hash32);
|
||||||
|
|
||||||
if (TestConfig.DEBUG()) {
|
if (test.it.utils.TestConfig.DEBUG()) {
|
||||||
TestLog.ok(op + ": localHash=" + localHashHex);
|
TestLog.ok(op + ": localHash=" + localHashHex);
|
||||||
TestLog.ok(op + ": serverLastGlobalHash=" + serverLastGlobalHash);
|
TestLog.ok(op + ": serverLastGlobalHash=" + serverLastGlobalHash);
|
||||||
}
|
}
|
||||||
@ -138,7 +144,7 @@ public final class AddBlockSender {
|
|||||||
// обновляем ChainState
|
// обновляем ChainState
|
||||||
state.applyAppendedBlock(globalNumber, lineIndex, lineNumber, hash32);
|
state.applyAppendedBlock(globalNumber, lineIndex, lineNumber, hash32);
|
||||||
|
|
||||||
if (TestConfig.DEBUG()) {
|
if (test.it.utils.TestConfig.DEBUG()) {
|
||||||
TestLog.ok(op + ": state updated");
|
TestLog.ok(op + ": state updated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,17 +172,7 @@ public final class AddBlockSender {
|
|||||||
private static void assert200(String op, String resp) {
|
private static void assert200(String op, String resp) {
|
||||||
int st = test.it.utils.JsonParsers.status(resp);
|
int st = test.it.utils.JsonParsers.status(resp);
|
||||||
assertEquals(200, st, op + ": expected status=200, but got=" + st + ", resp=" + resp);
|
assertEquals(200, st, op + ": expected status=200, but got=" + st + ", resp=" + resp);
|
||||||
if (TestConfig.DEBUG()) TestLog.ok(op + ": status=200");
|
if (test.it.utils.TestConfig.DEBUG()) TestLog.ok(op + ": status=200");
|
||||||
}
|
|
||||||
|
|
||||||
private static String extractPayloadString(String json, String field) {
|
|
||||||
try {
|
|
||||||
com.fasterxml.jackson.databind.JsonNode root =
|
|
||||||
new com.fasterxml.jackson.databind.ObjectMapper().readTree(json);
|
|
||||||
com.fasterxml.jackson.databind.JsonNode payload = root.get("payload");
|
|
||||||
if (payload != null && payload.has(field)) return payload.get(field).asText();
|
|
||||||
} catch (Exception ignore) {}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String base64(byte[] bytes) {
|
private static String base64(byte[] bytes) {
|
||||||
|
|||||||
@ -5,91 +5,104 @@ import utils.crypto.Ed25519Util;
|
|||||||
/**
|
/**
|
||||||
* Глобальный контекст IT прогона (одна JVM).
|
* Глобальный контекст IT прогона (одна JVM).
|
||||||
*
|
*
|
||||||
* ТЕПЕРЬ:
|
* БЫЛО:
|
||||||
* - login берётся из TestConfig.LOGIN()
|
* - один пользователь (login/device)
|
||||||
* - blockchainName = TestConfig.BCH_NAME()
|
|
||||||
* - ключи генерятся ДЕТЕРМИНИРОВАННО из login (как ты хотела)
|
|
||||||
*
|
*
|
||||||
* ПЛЮС:
|
* СТАЛО:
|
||||||
* - тесты можно запускать по одному — initIfNeeded() вызовется автоматически.
|
* - два пользователя (login1/device1 и login2/device2)
|
||||||
|
* - ключи детерминированы из логинов
|
||||||
*/
|
*/
|
||||||
public final class ItRunContext {
|
public final class ItRunContext {
|
||||||
|
|
||||||
private static final Object LOCK = new Object();
|
private static final Object LOCK = new Object();
|
||||||
private static volatile boolean inited = false;
|
private static volatile boolean inited = false;
|
||||||
|
|
||||||
private static String login;
|
private static String login1;
|
||||||
private static String blockchainName;
|
private static String bchName1;
|
||||||
|
|
||||||
private static byte[] loginPrivKey;
|
private static String login2;
|
||||||
private static byte[] loginPubKey;
|
private static String bchName2;
|
||||||
|
|
||||||
private static byte[] devicePrivKey;
|
private static byte[] login1PrivKey;
|
||||||
private static byte[] devicePubKey;
|
private static byte[] login1PubKey;
|
||||||
|
private static byte[] device1PrivKey;
|
||||||
|
private static byte[] device1PubKey;
|
||||||
|
|
||||||
|
private static byte[] login2PrivKey;
|
||||||
|
private static byte[] login2PubKey;
|
||||||
|
private static byte[] device2PrivKey;
|
||||||
|
private static byte[] device2PubKey;
|
||||||
|
|
||||||
private ItRunContext() {}
|
private ItRunContext() {}
|
||||||
|
|
||||||
/** Инициализировать, если ещё не инициализировано. */
|
|
||||||
public static void initIfNeeded() {
|
public static void initIfNeeded() {
|
||||||
if (inited) return;
|
if (inited) return;
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
if (inited) return;
|
if (inited) return;
|
||||||
|
|
||||||
login = TestConfig.LOGIN();
|
// USER1
|
||||||
blockchainName = TestConfig.BCH_NAME();
|
login1 = TestConfig.LOGIN();
|
||||||
|
bchName1 = TestConfig.BCH_NAME();
|
||||||
|
|
||||||
// 1) Генерация ключей ИЗ login
|
login1PrivKey = Ed25519Util.generatePrivateKeyFromString(login1);
|
||||||
// loginKey: приватный ключ = SHA-256(login)
|
login1PubKey = Ed25519Util.derivePublicKey(login1PrivKey);
|
||||||
loginPrivKey = Ed25519Util.generatePrivateKeyFromString(login);
|
|
||||||
loginPubKey = Ed25519Util.derivePublicKey(loginPrivKey);
|
|
||||||
|
|
||||||
// deviceKey: приватный ключ = SHA-256(login + "#device")
|
String deviceSeed1 = login1 + "#device";
|
||||||
String deviceSeedStr = login + "#device";
|
device1PrivKey = Ed25519Util.generatePrivateKeyFromString(deviceSeed1);
|
||||||
devicePrivKey = Ed25519Util.generatePrivateKeyFromString(deviceSeedStr);
|
device1PubKey = Ed25519Util.derivePublicKey(device1PrivKey);
|
||||||
devicePubKey = Ed25519Util.derivePublicKey(devicePrivKey);
|
|
||||||
|
// USER2
|
||||||
|
login2 = TestConfig.LOGIN2();
|
||||||
|
bchName2 = TestConfig.BCH_NAME2();
|
||||||
|
|
||||||
|
login2PrivKey = Ed25519Util.generatePrivateKeyFromString(login2);
|
||||||
|
login2PubKey = Ed25519Util.derivePublicKey(login2PrivKey);
|
||||||
|
|
||||||
|
String deviceSeed2 = login2 + "#device";
|
||||||
|
device2PrivKey = Ed25519Util.generatePrivateKeyFromString(deviceSeed2);
|
||||||
|
device2PubKey = Ed25519Util.derivePublicKey(device2PrivKey);
|
||||||
|
|
||||||
inited = true;
|
inited = true;
|
||||||
|
|
||||||
System.out.println(TestColors.C + "\n============================================================" + TestColors.R);
|
System.out.println(TestColors.C + "\n============================================================" + TestColors.R);
|
||||||
System.out.println(TestColors.C + "IT CONTEXT INIT: фиксированные данные из TestConfig" + TestColors.R);
|
System.out.println(TestColors.C + "IT CONTEXT INIT: 2 users" + TestColors.R);
|
||||||
System.out.println(TestColors.C + "============================================================" + TestColors.R);
|
System.out.println(TestColors.C + "============================================================" + TestColors.R);
|
||||||
System.out.println("login = " + login);
|
|
||||||
System.out.println("blockchainName = " + blockchainName);
|
System.out.println("USER1 login = " + login1);
|
||||||
System.out.println("loginPubKey = " + bytesToHexShort(loginPubKey));
|
System.out.println("USER1 blockchainName = " + bchName1);
|
||||||
System.out.println("devicePubKey = " + bytesToHexShort(devicePubKey));
|
System.out.println("USER1 loginPubKey = " + bytesToHexShort(login1PubKey));
|
||||||
|
System.out.println("USER1 devicePubKey = " + bytesToHexShort(device1PubKey));
|
||||||
|
System.out.println(TestColors.C + "------------------------------------------------------------" + TestColors.R);
|
||||||
|
|
||||||
|
System.out.println("USER2 login = " + login2);
|
||||||
|
System.out.println("USER2 blockchainName = " + bchName2);
|
||||||
|
System.out.println("USER2 loginPubKey = " + bytesToHexShort(login2PubKey));
|
||||||
|
System.out.println("USER2 devicePubKey = " + bytesToHexShort(device2PubKey));
|
||||||
System.out.println(TestColors.C + "------------------------------------------------------------\n" + TestColors.R);
|
System.out.println(TestColors.C + "------------------------------------------------------------\n" + TestColors.R);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String login() {
|
// =========================
|
||||||
initIfNeeded();
|
// USER1 getters
|
||||||
return login;
|
// =========================
|
||||||
}
|
public static String login1() { initIfNeeded(); return login1; }
|
||||||
|
public static String bchName1(){ initIfNeeded(); return bchName1; }
|
||||||
|
|
||||||
public static String blockchainName() {
|
public static byte[] login1PrivKey() { initIfNeeded(); return login1PrivKey.clone(); }
|
||||||
initIfNeeded();
|
public static byte[] login1PubKey() { initIfNeeded(); return login1PubKey.clone(); }
|
||||||
return blockchainName;
|
public static byte[] device1PrivKey(){ initIfNeeded(); return device1PrivKey.clone(); }
|
||||||
}
|
public static byte[] device1PubKey() { initIfNeeded(); return device1PubKey.clone(); }
|
||||||
|
|
||||||
public static byte[] loginPrivKey() {
|
// =========================
|
||||||
initIfNeeded();
|
// USER2 getters
|
||||||
return loginPrivKey.clone();
|
// =========================
|
||||||
}
|
public static String login2() { initIfNeeded(); return login2; }
|
||||||
|
public static String bchName2(){ initIfNeeded(); return bchName2; }
|
||||||
|
|
||||||
public static byte[] loginPubKey() {
|
public static byte[] login2PrivKey() { initIfNeeded(); return login2PrivKey.clone(); }
|
||||||
initIfNeeded();
|
public static byte[] login2PubKey() { initIfNeeded(); return login2PubKey.clone(); }
|
||||||
return loginPubKey.clone();
|
public static byte[] device2PrivKey(){ initIfNeeded(); return device2PrivKey.clone(); }
|
||||||
}
|
public static byte[] device2PubKey() { initIfNeeded(); return device2PubKey.clone(); }
|
||||||
|
|
||||||
public static byte[] devicePrivKey() {
|
|
||||||
initIfNeeded();
|
|
||||||
return devicePrivKey.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] devicePubKey() {
|
|
||||||
initIfNeeded();
|
|
||||||
return devicePubKey.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String bytesToHexShort(byte[] b) {
|
private static String bytesToHexShort(byte[] b) {
|
||||||
if (b == null) return "null";
|
if (b == null) return "null";
|
||||||
|
|||||||
@ -8,7 +8,37 @@ import java.util.Base64;
|
|||||||
public final class JsonBuilders {
|
public final class JsonBuilders {
|
||||||
private JsonBuilders(){}
|
private JsonBuilders(){}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// AddUser USER1 (как было)
|
||||||
|
// =========================
|
||||||
public static String addUser(String requestId) {
|
public static String addUser(String requestId) {
|
||||||
|
return addUserAny(
|
||||||
|
requestId,
|
||||||
|
TestConfig.LOGIN(),
|
||||||
|
TestConfig.BCH_NAME(),
|
||||||
|
TestConfig.LOGIN_PUBKEY_B64(),
|
||||||
|
TestConfig.DEVICE_PUBKEY_B64()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// AddUser USER2 (новое)
|
||||||
|
// =========================
|
||||||
|
public static String addUser2(String requestId) {
|
||||||
|
return addUserAny(
|
||||||
|
requestId,
|
||||||
|
TestConfig.LOGIN2(),
|
||||||
|
TestConfig.BCH_NAME2(),
|
||||||
|
TestConfig.LOGIN2_PUBKEY_B64(),
|
||||||
|
TestConfig.DEVICE2_PUBKEY_B64()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String addUserAny(String requestId,
|
||||||
|
String login,
|
||||||
|
String blockchainName,
|
||||||
|
String loginKeyB64,
|
||||||
|
String deviceKeyB64) {
|
||||||
return """
|
return """
|
||||||
{
|
{
|
||||||
"op": "AddUser",
|
"op": "AddUser",
|
||||||
@ -23,10 +53,10 @@ public final class JsonBuilders {
|
|||||||
}
|
}
|
||||||
""".formatted(
|
""".formatted(
|
||||||
requestId,
|
requestId,
|
||||||
TestConfig.LOGIN(),
|
login,
|
||||||
TestConfig.BCH_NAME(),
|
blockchainName,
|
||||||
TestConfig.LOGIN_PUBKEY_B64(),
|
loginKeyB64,
|
||||||
TestConfig.DEVICE_PUBKEY_B64(),
|
deviceKeyB64,
|
||||||
TestConfig.TEST_BCH_LIMIT
|
TestConfig.TEST_BCH_LIMIT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -43,7 +73,7 @@ public final class JsonBuilders {
|
|||||||
|
|
||||||
public static String createAuthSession(String requestId, String authNonce, String storagePwd) {
|
public static String createAuthSession(String requestId, String authNonce, String storagePwd) {
|
||||||
long timeMs = System.currentTimeMillis();
|
long timeMs = System.currentTimeMillis();
|
||||||
String sigB64 = signAuthorificated(authNonce, timeMs);
|
String sigB64 = signAuthorificated(authNonce, timeMs, TestConfig.DEVICE_PRIV_KEY());
|
||||||
|
|
||||||
return """
|
return """
|
||||||
{
|
{
|
||||||
@ -105,12 +135,17 @@ public final class JsonBuilders {
|
|||||||
/**
|
/**
|
||||||
* Подпись для режима AUTH_IN_PROGRESS:
|
* Подпись для режима AUTH_IN_PROGRESS:
|
||||||
* preimage = "AUTHORIFICATED:" + timeMs + authNonce
|
* preimage = "AUTHORIFICATED:" + timeMs + authNonce
|
||||||
* подписываем devicePrivKey (как в твоём протоколе).
|
* подписываем devicePrivKey.
|
||||||
*/
|
*/
|
||||||
public static String signAuthorificated(String authNonce, long timeMs) {
|
public static String signAuthorificated(String authNonce, long timeMs, byte[] devicePrivKey) {
|
||||||
String preimageStr = "AUTHORIFICATED:" + timeMs + authNonce;
|
String preimageStr = "AUTHORIFICATED:" + timeMs + authNonce;
|
||||||
byte[] preimage = preimageStr.getBytes(StandardCharsets.UTF_8);
|
byte[] preimage = preimageStr.getBytes(StandardCharsets.UTF_8);
|
||||||
byte[] sig = Ed25519Util.sign(preimage, TestConfig.DEVICE_PRIV_KEY());
|
byte[] sig = Ed25519Util.sign(preimage, devicePrivKey);
|
||||||
return Base64.getEncoder().encodeToString(sig);
|
return Base64.getEncoder().encodeToString(sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// старый метод оставим для совместимости
|
||||||
|
public static String signAuthorificated(String authNonce, long timeMs) {
|
||||||
|
return signAuthorificated(authNonce, timeMs, TestConfig.DEVICE_PRIV_KEY());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -5,19 +5,11 @@ import java.util.Base64;
|
|||||||
/**
|
/**
|
||||||
* Конфиг для IT тестов.
|
* Конфиг для IT тестов.
|
||||||
*
|
*
|
||||||
* ЛОГИКА:
|
* ДОБАВЛЕНО:
|
||||||
* - login по умолчанию берём из DEFAULT_LOGIN
|
* - Второй пользователь (LOGIN2) + его blockchainName и ключи.
|
||||||
* - можно переопределить запуском:
|
|
||||||
* -Dit.login=anya24
|
|
||||||
* -Dit.bchSuffix=001
|
|
||||||
*
|
*
|
||||||
* ВАЖНО:
|
* Важно:
|
||||||
* - ключи/имя блокчейна вычисляются из login (через ItRunContext).
|
* - Имена/ключи вычисляются детерминированно из логина (см. ItRunContext).
|
||||||
* - тесты можно запускать по отдельности, ItRunContext сам инициализируется при первом обращении.
|
|
||||||
*
|
|
||||||
* ЛОГИ:
|
|
||||||
* - детальный вывод включается флагом:
|
|
||||||
* -Dit.debug=true
|
|
||||||
*/
|
*/
|
||||||
public final class TestConfig {
|
public final class TestConfig {
|
||||||
|
|
||||||
@ -26,9 +18,12 @@ public final class TestConfig {
|
|||||||
// Твой WS URI
|
// Твой WS URI
|
||||||
public static final String WS_URI = "ws://localhost:7070/ws";
|
public static final String WS_URI = "ws://localhost:7070/ws";
|
||||||
|
|
||||||
// ======= По умолчанию (можно поменять под свою среду) =======
|
// ======= Пользователь #1 (по умолчанию) =======
|
||||||
public static final String DEFAULT_LOGIN = "Anya";
|
public static final String DEFAULT_LOGIN = "Anya";
|
||||||
|
|
||||||
|
// ======= Пользователь #2 (новый) =======
|
||||||
|
public static final String DEFAULT_LOGIN2 = "Anya2";
|
||||||
|
|
||||||
// Суффикс блокчейна по твоему правилу: login + 3 цифры
|
// Суффикс блокчейна по твоему правилу: login + 3 цифры
|
||||||
public static final String DEFAULT_BCH_SUFFIX_3 = "001";
|
public static final String DEFAULT_BCH_SUFFIX_3 = "001";
|
||||||
|
|
||||||
@ -38,51 +33,59 @@ public final class TestConfig {
|
|||||||
// Любая строка клиента (для логов)
|
// Любая строка клиента (для логов)
|
||||||
public static final String TEST_CLIENT_INFO = "it-tests";
|
public static final String TEST_CLIENT_INFO = "it-tests";
|
||||||
|
|
||||||
/** DEBUG-режим: подробные логи отправки/получения/ожиданий (по умолчанию false). */
|
/** DEBUG-режим: подробные логи (по умолчанию true, как у тебя). */
|
||||||
public static boolean DEBUG() {
|
public static boolean DEBUG() {
|
||||||
return Boolean.parseBoolean(System.getProperty("it.debug", "true"));
|
return Boolean.parseBoolean(System.getProperty("it.debug", "true"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** login для прогона (по умолчанию DEFAULT_LOGIN, можно переопределить -Dit.login=...). */
|
// =========================
|
||||||
|
// USER #1
|
||||||
|
// =========================
|
||||||
|
|
||||||
|
/** login для прогона (user1). */
|
||||||
public static String LOGIN() {
|
public static String LOGIN() {
|
||||||
return System.getProperty("it.login", DEFAULT_LOGIN);
|
return System.getProperty("it.login", DEFAULT_LOGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Суффикс для имени блокчейна (по умолчанию DEFAULT_BCH_SUFFIX_3, можно переопределить -Dit.bchSuffix=...). */
|
/** Суффикс для имени блокчейна (user1). */
|
||||||
public static String BCH_SUFFIX_3() {
|
public static String BCH_SUFFIX_3() {
|
||||||
return System.getProperty("it.bchSuffix", DEFAULT_BCH_SUFFIX_3);
|
return System.getProperty("it.bchSuffix", DEFAULT_BCH_SUFFIX_3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** blockchainName по правилу: login + суффикс. */
|
/** blockchainName по правилу: login + суффикс (user1). */
|
||||||
public static String BCH_NAME() {
|
public static String BCH_NAME() {
|
||||||
return LOGIN() + BCH_SUFFIX_3();
|
return LOGIN() + BCH_SUFFIX_3();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ======= Ключи (берём из ItRunContext) =======
|
public static byte[] LOGIN_PRIV_KEY() { return ItRunContext.login1PrivKey(); }
|
||||||
|
public static byte[] LOGIN_PUB_KEY() { return ItRunContext.login1PubKey(); }
|
||||||
|
public static byte[] DEVICE_PRIV_KEY(){ return ItRunContext.device1PrivKey(); }
|
||||||
|
public static byte[] DEVICE_PUB_KEY() { return ItRunContext.device1PubKey(); }
|
||||||
|
|
||||||
public static byte[] LOGIN_PRIV_KEY() {
|
public static String LOGIN_PUBKEY_B64() { return Base64.getEncoder().encodeToString(LOGIN_PUB_KEY()); }
|
||||||
return ItRunContext.loginPrivKey();
|
public static String DEVICE_PUBKEY_B64() { return Base64.getEncoder().encodeToString(DEVICE_PUB_KEY()); }
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// USER #2
|
||||||
|
// =========================
|
||||||
|
|
||||||
|
/** login второго пользователя. Можно переопределить -Dit.login2=... */
|
||||||
|
public static String LOGIN2() {
|
||||||
|
return System.getProperty("it.login2", DEFAULT_LOGIN2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] LOGIN_PUB_KEY() {
|
/** blockchainName второго: login2 + тот же суффикс. */
|
||||||
return ItRunContext.loginPubKey();
|
public static String BCH_NAME2() {
|
||||||
|
return LOGIN2() + BCH_SUFFIX_3();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] DEVICE_PRIV_KEY() {
|
public static byte[] LOGIN2_PRIV_KEY() { return ItRunContext.login2PrivKey(); }
|
||||||
return ItRunContext.devicePrivKey();
|
public static byte[] LOGIN2_PUB_KEY() { return ItRunContext.login2PubKey(); }
|
||||||
}
|
public static byte[] DEVICE2_PRIV_KEY() { return ItRunContext.device2PrivKey(); }
|
||||||
|
public static byte[] DEVICE2_PUB_KEY() { return ItRunContext.device2PubKey(); }
|
||||||
|
|
||||||
public static byte[] DEVICE_PUB_KEY() {
|
public static String LOGIN2_PUBKEY_B64() { return Base64.getEncoder().encodeToString(LOGIN2_PUB_KEY()); }
|
||||||
return ItRunContext.devicePubKey();
|
public static String DEVICE2_PUBKEY_B64() { return Base64.getEncoder().encodeToString(DEVICE2_PUB_KEY()); }
|
||||||
}
|
|
||||||
|
|
||||||
public static String LOGIN_PUBKEY_B64() {
|
|
||||||
return Base64.getEncoder().encodeToString(LOGIN_PUB_KEY());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String DEVICE_PUBKEY_B64() {
|
|
||||||
return Base64.getEncoder().encodeToString(DEVICE_PUB_KEY());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Псевдо-пароль хранилища — достаточно для тестов. */
|
/** Псевдо-пароль хранилища — достаточно для тестов. */
|
||||||
public static String fakeStoragePwd() {
|
public static String fakeStoragePwd() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user