28 12 25
Старая версия. Вроде там тесты доделал что бы работали
This commit is contained in:
parent
809d897da6
commit
1526392ca5
46
build.gradle
46
build.gradle
@ -51,6 +51,43 @@ dependencies {
|
||||
implementation project(':shine-server-net-server') // Хэндлеры для обработки сетевых запросов
|
||||
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// // -------------------- ТЕСТЫ --------------------
|
||||
// testImplementation platform('org.junit:junit-bom:5.11.4')
|
||||
// testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||
// testImplementation 'org.junit.platform:junit-platform-suite-api'
|
||||
// testRuntimeOnly 'org.junit.platform:junit-platform-suite-engine'
|
||||
//
|
||||
// testRuntimeOnly "org.junit.platform:junit-platform-launcher"
|
||||
//
|
||||
// // Suite (чтобы запустить классы в заданном порядке)
|
||||
// testImplementation "org.junit.platform:junit-platform-suite:1.10.2"
|
||||
//
|
||||
// // Нужно, чтобы TestExecutionListener (RussianSummaryListener) корректно подхватывался
|
||||
// testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||
//}
|
||||
|
||||
// -------------------- ТЕСТЫ (JUnit 5) --------------------
|
||||
// Один BOM на всё семейство JUnit (Jupiter + Platform модули)
|
||||
testImplementation platform("org.junit:junit-bom:5.10.2")
|
||||
|
||||
// JUnit Jupiter (Test, BeforeAll, Assertions)
|
||||
testImplementation "org.junit.jupiter:junit-jupiter"
|
||||
|
||||
// JUnit Platform Suite (@Suite, @SelectClasses)
|
||||
testImplementation "org.junit.platform:junit-platform-suite-api"
|
||||
testRuntimeOnly "org.junit.platform:junit-platform-suite-engine"
|
||||
|
||||
// Нужно для компиляции RussianSummaryListener (org.junit.platform.launcher.*)
|
||||
// и чтобы JUnit мог подхватить listener при запуске
|
||||
testImplementation "org.junit.platform:junit-platform-launcher"
|
||||
testRuntimeOnly "org.junit.platform:junit-platform-launcher"
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
application {
|
||||
@ -79,12 +116,3 @@ shadowJar {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
|
||||
testLogging {
|
||||
events "passed", "skipped", "failed"
|
||||
showStandardStreams = true
|
||||
}
|
||||
}
|
||||
|
||||
16
src/test/concat_to_file.sh
Executable file
16
src/test/concat_to_file.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
OUTFILE="all_files.txt"
|
||||
|
||||
# очищаем или создаём файл
|
||||
: > "$OUTFILE"
|
||||
|
||||
# собрать только *.java файлы и вывести их содержимое в файл
|
||||
find . -type f -name "*.java" | sort | while read -r f; do
|
||||
cat "$f" >> "$OUTFILE"
|
||||
echo >> "$OUTFILE" # пустая строка-разделитель
|
||||
done
|
||||
|
||||
echo "Готово! Все .java файлы собраны в $OUTFILE"
|
||||
|
||||
24
src/test/java/test/it/IT_00_Suite.java
Normal file
24
src/test/java/test/it/IT_00_Suite.java
Normal file
@ -0,0 +1,24 @@
|
||||
package test.it;
|
||||
|
||||
import org.junit.platform.suite.api.SelectClasses;
|
||||
import org.junit.platform.suite.api.Suite;
|
||||
import test.it.ws.*;
|
||||
|
||||
/**
|
||||
* Сьют, который запускает IT тесты строго в заданном порядке.
|
||||
*
|
||||
* Запуск:
|
||||
* ./gradlew test --tests test.it.IT_00_Suite
|
||||
*
|
||||
* Важно:
|
||||
* - ItRunContext.initOnce() будет вызван слушателем RussianSummaryListener ДО тестов.
|
||||
*/
|
||||
@Suite
|
||||
@SelectClasses({
|
||||
IT_01_AddUser.class,
|
||||
IT_02_Sessions.class,
|
||||
IT_03_AddBlock_NoAuth.class
|
||||
})
|
||||
public class IT_00_Suite {
|
||||
// пусто
|
||||
}
|
||||
128
src/test/java/test/it/utils/ItRunContext.java
Normal file
128
src/test/java/test/it/utils/ItRunContext.java
Normal file
@ -0,0 +1,128 @@
|
||||
package test.it.utils;
|
||||
|
||||
import utils.crypto.Ed25519Util;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Глобальный контекст интеграционного прогона (один запуск Gradle test).
|
||||
*
|
||||
* ВАЖНО:
|
||||
* - инициализируется ровно один раз на весь процесс JVM;
|
||||
* - хранит случайный login + blockchainName + ключи, чтобы все IT тесты работали в одной "сессии данных".
|
||||
*/
|
||||
public final class ItRunContext {
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
private static volatile boolean inited = false;
|
||||
|
||||
private static String login;
|
||||
private static String blockchainName;
|
||||
|
||||
private static byte[] loginPrivKey;
|
||||
private static byte[] loginPubKey;
|
||||
|
||||
private static byte[] devicePrivKey;
|
||||
private static byte[] devicePubKey;
|
||||
|
||||
private ItRunContext() {}
|
||||
|
||||
public static void initOnce() {
|
||||
if (inited) return;
|
||||
synchronized (LOCK) {
|
||||
if (inited) return;
|
||||
|
||||
// 1) Генерим читаемый суффикс по времени + случайности, чтобы не было коллизий.
|
||||
String ts = LocalDateTime.now()
|
||||
.format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss", Locale.ROOT));
|
||||
|
||||
String rnd = randomBase32(6).toLowerCase(Locale.ROOT);
|
||||
|
||||
// login должен быть валидным по твоим правилам (латиница + цифры + _)
|
||||
// Пример: it_20251226_173012_ab12cd
|
||||
login = "it_" + ts + "_" + rnd;
|
||||
|
||||
// 2) blockchainName по правилу: login + 4 цифры
|
||||
blockchainName = login + TestConfig.BCH_SUFFIX_3;
|
||||
|
||||
// 3) Генерация ключей ИЗ login (как ты попросила)
|
||||
// loginKey: приватный ключ = SHA-256(login)
|
||||
loginPrivKey = Ed25519Util.generatePrivateKeyFromString(login);
|
||||
loginPubKey = Ed25519Util.derivePublicKey(loginPrivKey);
|
||||
|
||||
// deviceKey: приватный ключ = SHA-256(login + "#device")
|
||||
String deviceSeedStr = login + "#device";
|
||||
devicePrivKey = Ed25519Util.generatePrivateKeyFromString(deviceSeedStr);
|
||||
devicePubKey = Ed25519Util.derivePublicKey(devicePrivKey);
|
||||
|
||||
inited = true;
|
||||
|
||||
System.out.println(TestColors.C + "\n============================================================" + TestColors.R);
|
||||
System.out.println(TestColors.C + "IT ПРОГОН: сгенерированы случайные данные" + TestColors.R);
|
||||
System.out.println(TestColors.C + "============================================================" + TestColors.R);
|
||||
System.out.println("login = " + login);
|
||||
System.out.println("blockchainName = " + blockchainName);
|
||||
System.out.println("loginPubKey = " + bytesToHexShort(loginPubKey));
|
||||
System.out.println("devicePubKey = " + bytesToHexShort(devicePubKey));
|
||||
System.out.println(TestColors.C + "------------------------------------------------------------\n" + TestColors.R);
|
||||
}
|
||||
}
|
||||
|
||||
public static String login() {
|
||||
ensureInit();
|
||||
return login;
|
||||
}
|
||||
|
||||
public static String blockchainName() {
|
||||
ensureInit();
|
||||
return blockchainName;
|
||||
}
|
||||
|
||||
public static byte[] loginPrivKey() {
|
||||
ensureInit();
|
||||
return loginPrivKey.clone();
|
||||
}
|
||||
|
||||
public static byte[] loginPubKey() {
|
||||
ensureInit();
|
||||
return loginPubKey.clone();
|
||||
}
|
||||
|
||||
public static byte[] devicePrivKey() {
|
||||
ensureInit();
|
||||
return devicePrivKey.clone();
|
||||
}
|
||||
|
||||
public static byte[] devicePubKey() {
|
||||
ensureInit();
|
||||
return devicePubKey.clone();
|
||||
}
|
||||
|
||||
private static void ensureInit() {
|
||||
if (!inited) {
|
||||
throw new IllegalStateException("ItRunContext ещё не инициализирован. Он должен быть вызван до тестов (через RussianSummaryListener).");
|
||||
}
|
||||
}
|
||||
|
||||
private static String randomBase32(int len) {
|
||||
final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
SecureRandom r = new SecureRandom();
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
sb.append(alphabet.charAt(r.nextInt(alphabet.length())));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String bytesToHexShort(byte[] b) {
|
||||
if (b == null) return "null";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int n = Math.min(b.length, 10);
|
||||
for (int i = 0; i < n; i++) sb.append(String.format("%02x", b[i]));
|
||||
if (b.length > n) sb.append("...");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -23,10 +23,10 @@ public final class JsonBuilders {
|
||||
}
|
||||
""".formatted(
|
||||
requestId,
|
||||
TestConfig.TEST_LOGIN,
|
||||
TestConfig.TEST_BCH_NAME,
|
||||
TestConfig.LOGIN_PUBKEY_B64,
|
||||
TestConfig.DEVICE_PUBKEY_B64,
|
||||
TestConfig.TEST_LOGIN(),
|
||||
TestConfig.TEST_BCH_NAME(),
|
||||
TestConfig.LOGIN_PUBKEY_B64(),
|
||||
TestConfig.DEVICE_PUBKEY_B64(),
|
||||
TestConfig.TEST_BCH_LIMIT
|
||||
);
|
||||
}
|
||||
@ -38,7 +38,7 @@ public final class JsonBuilders {
|
||||
"requestId": "%s",
|
||||
"payload": { "login": "%s" }
|
||||
}
|
||||
""".formatted(requestId, TestConfig.TEST_LOGIN);
|
||||
""".formatted(requestId, TestConfig.TEST_LOGIN());
|
||||
}
|
||||
|
||||
public static String createAuthSession(String requestId, String authNonce, String storagePwd) {
|
||||
@ -102,10 +102,15 @@ public final class JsonBuilders {
|
||||
""".formatted(requestId, sessionId, timeMs, signatureB64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Подпись для режима AUTH_IN_PROGRESS:
|
||||
* preimage = "AUTHORIFICATED:" + timeMs + authNonce
|
||||
* подписываем devicePrivKey (как в твоём протоколе).
|
||||
*/
|
||||
public static String signAuthorificated(String authNonce, long timeMs) {
|
||||
String preimageStr = "AUTHORIFICATED:" + timeMs + authNonce;
|
||||
byte[] preimage = preimageStr.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] sig = Ed25519Util.sign(preimage, TestConfig.DEVICE_PRIV_KEY);
|
||||
byte[] sig = Ed25519Util.sign(preimage, TestConfig.DEVICE_PRIV_KEY());
|
||||
return Base64.getEncoder().encodeToString(sig);
|
||||
}
|
||||
}
|
||||
90
src/test/java/test/it/utils/RussianSummaryListener.java
Normal file
90
src/test/java/test/it/utils/RussianSummaryListener.java
Normal file
@ -0,0 +1,90 @@
|
||||
package test.it.utils;
|
||||
|
||||
import org.junit.platform.launcher.TestExecutionListener;
|
||||
import org.junit.platform.launcher.TestIdentifier;
|
||||
import org.junit.platform.launcher.TestPlan;
|
||||
import org.junit.platform.engine.TestExecutionResult;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Слушатель JUnit, который в конце прогона печатает "главный отчёт" по-русски.
|
||||
*
|
||||
* Подключается через src/test/resources/junit-platform.properties
|
||||
*/
|
||||
public class RussianSummaryListener implements TestExecutionListener {
|
||||
|
||||
private final List<String> failed = new ArrayList<>();
|
||||
private int total = 0;
|
||||
private int passed = 0;
|
||||
private int skipped = 0;
|
||||
|
||||
@Override
|
||||
public void testPlanExecutionStarted(TestPlan testPlan) {
|
||||
// Инициализируем данные прогона прямо тут, чтобы гарантированно до тестов
|
||||
ItRunContext.initOnce();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
|
||||
if (!testIdentifier.isTest()) return;
|
||||
|
||||
total++;
|
||||
|
||||
switch (testExecutionResult.getStatus()) {
|
||||
case SUCCESSFUL -> passed++;
|
||||
case ABORTED -> skipped++;
|
||||
case FAILED -> {
|
||||
String name = prettyName(testIdentifier);
|
||||
String msg = testExecutionResult.getThrowable()
|
||||
.map(t -> t.getClass().getSimpleName() + ": " + safeMsg(t.getMessage()))
|
||||
.orElse("Причина неизвестна");
|
||||
failed.add(name + " — " + msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testPlanExecutionFinished(TestPlan testPlan) {
|
||||
System.out.println(TestColors.C + "\n============================================================" + TestColors.R);
|
||||
System.out.println(TestColors.C + "ГЛАВНЫЙ ОТЧЁТ IT ПРОГОНА" + TestColors.R);
|
||||
System.out.println(TestColors.C + "============================================================" + TestColors.R);
|
||||
|
||||
System.out.println("Всего тестов: " + total);
|
||||
System.out.println(TestColors.G + "Прошло: " + passed + TestColors.R);
|
||||
System.out.println(TestColors.Y + "Пропущено: " + skipped + TestColors.R);
|
||||
System.out.println(TestColors.RED + "Упало: " + failed.size() + TestColors.R);
|
||||
|
||||
if (failed.isEmpty()) {
|
||||
System.out.println(TestColors.G + "\n✅ ВСЕ ТЕСТЫ ПРОШЛИ УСПЕШНО" + TestColors.R);
|
||||
} else {
|
||||
System.out.println(TestColors.RED + "\n❌ СПИСОК УПАВШИХ ТЕСТОВ:" + TestColors.R);
|
||||
for (int i = 0; i < failed.size(); i++) {
|
||||
System.out.println(TestColors.RED + (i + 1) + ") " + failed.get(i) + TestColors.R);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println(TestColors.C + "------------------------------------------------------------" + TestColors.R);
|
||||
System.out.println("login = " + ItRunContext.login());
|
||||
System.out.println("blockchainName = " + ItRunContext.blockchainName());
|
||||
System.out.println(TestColors.C + "============================================================\n" + TestColors.R);
|
||||
}
|
||||
|
||||
private static String prettyName(TestIdentifier id) {
|
||||
// displayName обычно типа: "addUser_shouldReturn200_orAlreadyExists()"
|
||||
// Добавим класс, если удастся вытащить из legacyId (обычно там есть полное имя)
|
||||
String dn = id.getDisplayName();
|
||||
String legacy = id.getLegacyReportingName(); // часто содержит "test.it.IT_01_AddUser"
|
||||
if (legacy != null && !legacy.isBlank()) {
|
||||
return legacy + " :: " + (dn == null ? "test" : dn);
|
||||
}
|
||||
return dn == null ? "test" : dn;
|
||||
}
|
||||
|
||||
private static String safeMsg(String s) {
|
||||
if (s == null) return "";
|
||||
return s.replace("\n", " ").replace("\r", " ");
|
||||
}
|
||||
}
|
||||
12
src/test/java/test/it/utils/TestColors.java
Normal file
12
src/test/java/test/it/utils/TestColors.java
Normal file
@ -0,0 +1,12 @@
|
||||
package test.it.utils;
|
||||
|
||||
/** ANSI цвета для красивого вывода в терминал. */
|
||||
public final class TestColors {
|
||||
private TestColors() {}
|
||||
|
||||
public static final String R = "\u001B[0m";
|
||||
public static final String G = "\u001B[32m";
|
||||
public static final String Y = "\u001B[33m";
|
||||
public static final String RED = "\u001B[31m";
|
||||
public static final String C = "\u001B[36m";
|
||||
}
|
||||
@ -1,37 +1,63 @@
|
||||
package test.it.utils;
|
||||
|
||||
import utils.crypto.Ed25519Util;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Конфиг для IT тестов.
|
||||
*
|
||||
* ВАЖНО:
|
||||
* - login/blockchainName/ключи берём из ItRunContext (случайные на каждый прогон).
|
||||
*/
|
||||
public final class TestConfig {
|
||||
private TestConfig(){}
|
||||
|
||||
private TestConfig() {}
|
||||
|
||||
// Твой WS URI
|
||||
public static final String WS_URI = "ws://localhost:7070/ws";
|
||||
public static final String TEST_LOGIN = "anya24";
|
||||
public static final String TEST_BCH_NAME = TEST_LOGIN + "001";
|
||||
public static final int TEST_BCH_LIMIT = 1_000_000;
|
||||
public static final String TEST_CLIENT_INFO = "JavaTestClient/1.0";
|
||||
|
||||
public static final byte[] LOGIN_PRIV_KEY;
|
||||
public static final String LOGIN_PUBKEY_B64;
|
||||
// Суффикс блокчейна по твоему правилу: login + 3 цифры
|
||||
public static final String BCH_SUFFIX_3 = "001";
|
||||
|
||||
public static final byte[] DEVICE_PRIV_KEY;
|
||||
public static final String DEVICE_PUBKEY_B64;
|
||||
// Лимит блокчейна для AddUser
|
||||
public static final long TEST_BCH_LIMIT = 50_000_000L;
|
||||
|
||||
static {
|
||||
LOGIN_PRIV_KEY = Ed25519Util.generatePrivateKeyFromString("test-ed25519-login-11" + TEST_LOGIN);
|
||||
byte[] loginPub = Ed25519Util.derivePublicKey(LOGIN_PRIV_KEY);
|
||||
LOGIN_PUBKEY_B64 = Ed25519Util.keyToBase64(loginPub);
|
||||
// Любая строка клиента (для логов)
|
||||
public static final String TEST_CLIENT_INFO = "it-tests";
|
||||
|
||||
DEVICE_PRIV_KEY = Ed25519Util.generatePrivateKeyFromString("test-ed25519-device-" + TEST_LOGIN);
|
||||
byte[] devicePub = Ed25519Util.derivePublicKey(DEVICE_PRIV_KEY);
|
||||
DEVICE_PUBKEY_B64 = Ed25519Util.keyToBase64(devicePub);
|
||||
public static String TEST_LOGIN() {
|
||||
return ItRunContext.login();
|
||||
}
|
||||
|
||||
public static String TEST_BCH_NAME() {
|
||||
return ItRunContext.blockchainName();
|
||||
}
|
||||
|
||||
public static byte[] LOGIN_PRIV_KEY() {
|
||||
return ItRunContext.loginPrivKey();
|
||||
}
|
||||
|
||||
public static byte[] LOGIN_PUB_KEY() {
|
||||
return ItRunContext.loginPubKey();
|
||||
}
|
||||
|
||||
public static byte[] DEVICE_PRIV_KEY() {
|
||||
return ItRunContext.devicePrivKey();
|
||||
}
|
||||
|
||||
public static byte[] DEVICE_PUB_KEY() {
|
||||
return ItRunContext.devicePubKey();
|
||||
}
|
||||
|
||||
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() {
|
||||
byte[] data = new byte[32];
|
||||
for (int i = 0; i < data.length; i++) data[i] = (byte) (i + 1);
|
||||
return Base64.getEncoder().encodeToString(data);
|
||||
return "pwd-" + System.nanoTime();
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package test.it;
|
||||
package test.it.ws;
|
||||
|
||||
import blockchain.BchBlockEntry;
|
||||
import blockchain.BchCryptoVerifier;
|
||||
@ -23,7 +23,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
* IT_03_AddBlock_NoAuth
|
||||
*
|
||||
* Интеграционный тест добавления блоков в персональный блокчейн без отдельной авторизации,
|
||||
* в формате твоих IT-тестов (ANSI, шаги, WsTestClient, JsonBuilders/JsonParsers).
|
||||
* в формате твоих IT-тестов (ANSI, шаги, WsTestClient).
|
||||
*
|
||||
* Сценарий:
|
||||
* 1) AddBlock: HEADER (global=0, prevGlobalHash=ZERO64) -> ожидаем 200
|
||||
@ -31,11 +31,12 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
* 2) AddBlock: TEXT (global=1, prevGlobalHash=serverLastGlobalHash) -> ожидаем 200
|
||||
*
|
||||
* Примечание:
|
||||
* - lastLineHash пока равен lastGlobalHash (как ты говорил).
|
||||
* - lastLineHash пока равен lastGlobalHash.
|
||||
* - подпись блока делаем ключом логина (loginPrivKey).
|
||||
*/
|
||||
public class IT_03_AddBlock_NoAuth {
|
||||
|
||||
// ANSI цвета (работает в большинстве терминалов)
|
||||
// ANSI цвета
|
||||
private static final String R = "\u001B[0m";
|
||||
private static final String G = "\u001B[32m";
|
||||
private static final String Y = "\u001B[33m";
|
||||
@ -63,10 +64,6 @@ public class IT_03_AddBlock_NoAuth {
|
||||
System.out.println(G + "✅ " + s + R);
|
||||
}
|
||||
|
||||
private static void warn(String s) {
|
||||
System.out.println(Y + "⚠️ " + s + R);
|
||||
}
|
||||
|
||||
private static void boom(String s) {
|
||||
System.out.println(RED + "****************************************************************" + R);
|
||||
System.out.println(RED + "❌ " + s + R);
|
||||
@ -137,21 +134,19 @@ public class IT_03_AddBlock_NoAuth {
|
||||
|
||||
try (WsTestClient client = new WsTestClient(TestConfig.WS_URI)) {
|
||||
|
||||
// =================================================================================
|
||||
// ШАГ 1: HEADER (global=0)
|
||||
// =================================================================================
|
||||
// -------------------- ШАГ 1: HEADER (global=0) --------------------
|
||||
stepTitle("ШАГ 1: AddBlock HEADER (global=0)");
|
||||
|
||||
byte[] headerFull = buildHeaderBlockFullBytes(
|
||||
0, // globalNumber
|
||||
(short) 0, // lineIndex
|
||||
0, // lineBlockNumber
|
||||
ZERO32, // prevGlobalHash32
|
||||
ZERO32 // prevLineHash32 (пока равно prevGlobal)
|
||||
0,
|
||||
(short) 0,
|
||||
0,
|
||||
ZERO32,
|
||||
ZERO32
|
||||
);
|
||||
|
||||
String reqId1 = "it03-add-header";
|
||||
String reqJson1 = buildAddBlockJson(reqId1, TestConfig.TEST_BCH_NAME, 0, ZERO64, base64(headerFull));
|
||||
String reqJson1 = buildAddBlockJson(reqId1, TestConfig.TEST_BCH_NAME(), 0, ZERO64, base64(headerFull));
|
||||
|
||||
send("AddBlock#HEADER", reqJson1);
|
||||
String resp1 = client.request(reqId1, reqJson1, Duration.ofSeconds(8));
|
||||
@ -166,25 +161,23 @@ public class IT_03_AddBlock_NoAuth {
|
||||
|
||||
ok("HEADER принят. serverLastGlobalHash=" + serverLastGlobalHash);
|
||||
|
||||
// =================================================================================
|
||||
// ШАГ 2: TEXT (global=1)
|
||||
// =================================================================================
|
||||
// -------------------- ШАГ 2: TEXT (global=1) --------------------
|
||||
stepTitle("ШАГ 2: AddBlock TEXT (global=1)");
|
||||
|
||||
byte[] prevGlobal32 = hexToBytes32(serverLastGlobalHash);
|
||||
byte[] prevLine32 = prevGlobal32; // пока lineHash = globalHash
|
||||
byte[] prevLine32 = prevGlobal32;
|
||||
|
||||
byte[] textFull = buildTextBlockFullBytes(
|
||||
1, // globalNumber
|
||||
(short) 0, // lineIndex
|
||||
1, // lineBlockNumber
|
||||
1,
|
||||
(short) 0,
|
||||
1,
|
||||
prevGlobal32,
|
||||
prevLine32,
|
||||
"Hello from IT_03 test"
|
||||
);
|
||||
|
||||
String reqId2 = "it03-add-text";
|
||||
String reqJson2 = buildAddBlockJson(reqId2, TestConfig.TEST_BCH_NAME, 1, serverLastGlobalHash, base64(textFull));
|
||||
String reqJson2 = buildAddBlockJson(reqId2, TestConfig.TEST_BCH_NAME(), 1, serverLastGlobalHash, base64(textFull));
|
||||
|
||||
send("AddBlock#TEXT", reqJson2);
|
||||
String resp2 = client.request(reqId2, reqJson2, Duration.ofSeconds(8));
|
||||
@ -201,7 +194,7 @@ public class IT_03_AddBlock_NoAuth {
|
||||
}
|
||||
|
||||
// =================================================================================
|
||||
// BUILD BLOCKS
|
||||
// BUILD BLOCKS
|
||||
// =================================================================================
|
||||
|
||||
private static byte[] buildHeaderBlockFullBytes(int globalNumber,
|
||||
@ -210,9 +203,7 @@ public class IT_03_AddBlock_NoAuth {
|
||||
byte[] prevGlobalHash32,
|
||||
byte[] prevLineHash32) {
|
||||
|
||||
// HeaderBody формата type=0 ver=1:
|
||||
// [type][ver][tag "SHiNE001"][loginLen][login]
|
||||
HeaderBody body = new HeaderBody(TestConfig.TEST_LOGIN);
|
||||
HeaderBody body = new HeaderBody(TestConfig.TEST_LOGIN());
|
||||
byte[] bodyBytes = body.toBytes();
|
||||
|
||||
return buildSignedBlockFullBytes(globalNumber, lineIndex, lineBlockNumber, bodyBytes, prevGlobalHash32, prevLineHash32);
|
||||
@ -240,7 +231,6 @@ public class IT_03_AddBlock_NoAuth {
|
||||
|
||||
long ts = System.currentTimeMillis() / 1000L;
|
||||
|
||||
// recordSize = RAW header + body (без подписи/хэша — это внутренняя "raw"-часть записи)
|
||||
int recordSize = BchBlockEntry.RAW_HEADER_SIZE + bodyBytes.length;
|
||||
|
||||
byte[] rawBytes = ByteBuffer.allocate(recordSize)
|
||||
@ -254,7 +244,7 @@ public class IT_03_AddBlock_NoAuth {
|
||||
.array();
|
||||
|
||||
byte[] preimage = BchCryptoVerifier.buildPreimage(
|
||||
TestConfig.TEST_LOGIN,
|
||||
TestConfig.TEST_LOGIN(),
|
||||
prevGlobalHash32,
|
||||
prevLineHash32,
|
||||
rawBytes
|
||||
@ -262,8 +252,8 @@ public class IT_03_AddBlock_NoAuth {
|
||||
|
||||
byte[] hash32 = BchCryptoVerifier.sha256(preimage);
|
||||
|
||||
// В этом тесте подпись делаем ключом логина (как у тебя было)
|
||||
byte[] signature64 = Ed25519Util.sign(hash32, TestConfig.LOGIN_PRIV_KEY);
|
||||
// Подпись делаем ключом логина
|
||||
byte[] signature64 = Ed25519Util.sign(hash32, TestConfig.LOGIN_PRIV_KEY());
|
||||
|
||||
return new BchBlockEntry(
|
||||
globalNumber,
|
||||
@ -276,15 +266,11 @@ public class IT_03_AddBlock_NoAuth {
|
||||
).toBytes();
|
||||
}
|
||||
|
||||
// =================================================================================
|
||||
// JSON BUILD
|
||||
// =================================================================================
|
||||
|
||||
private static String buildAddBlockJson(String requestId,
|
||||
String blockchainName,
|
||||
int globalNumber,
|
||||
String prevGlobalHashHex,
|
||||
String blockBytesB64) {
|
||||
String blockchainName,
|
||||
int globalNumber,
|
||||
String prevGlobalHashHex,
|
||||
String blockBytesB64) {
|
||||
return """
|
||||
{
|
||||
"op": "AddBlock",
|
||||
@ -299,14 +285,8 @@ public class IT_03_AddBlock_NoAuth {
|
||||
""".formatted(requestId, blockchainName, globalNumber, prevGlobalHashHex, blockBytesB64);
|
||||
}
|
||||
|
||||
// =================================================================================
|
||||
// HELPERS
|
||||
// =================================================================================
|
||||
|
||||
private static String extractPayloadString(String json, String field) {
|
||||
try {
|
||||
// JsonParsers у тебя уже есть, но тут проще и не ломать совместимость:
|
||||
// Если захочешь — можем добавить в JsonParsers отдельный метод payloadString(...)
|
||||
com.fasterxml.jackson.databind.JsonNode root =
|
||||
new com.fasterxml.jackson.databind.ObjectMapper().readTree(json);
|
||||
com.fasterxml.jackson.databind.JsonNode payload = root.get("payload");
|
||||
|
||||
5
src/test/resources/junit-platform.properties
Normal file
5
src/test/resources/junit-platform.properties
Normal file
@ -0,0 +1,5 @@
|
||||
# ???????????? ??? ?????????, ????? ? ????? ??????? ??? "??????? ?????" ??-??????
|
||||
junit.platform.listeners.default=test.it.utils.RussianSummaryListener
|
||||
|
||||
# ?? ?????? ??????: ????????? ???????????? ?????????? ?? ?????? JUnit
|
||||
junit.jupiter.execution.parallel.enabled=false
|
||||
Loading…
Reference in New Issue
Block a user