23 12 25
Сессии работают пользователи добавляются. И тесты красиво выводият коменты. Старый класс теста больше не нужен
This commit is contained in:
parent
c515d5287e
commit
b5fa05a660
@ -1,524 +0,0 @@
|
|||||||
//package shine.auth;
|
|
||||||
//
|
|
||||||
//import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
//import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
//import org.junit.jupiter.api.Assertions;
|
|
||||||
//import org.junit.jupiter.api.Test;
|
|
||||||
//import utils.crypto.Ed25519Util;
|
|
||||||
//
|
|
||||||
//import java.net.URI;
|
|
||||||
//import java.net.http.HttpClient;
|
|
||||||
//import java.net.http.WebSocket;
|
|
||||||
//import java.nio.charset.StandardCharsets;
|
|
||||||
//import java.time.Duration;
|
|
||||||
//import java.util.Base64;
|
|
||||||
//import java.util.UUID;
|
|
||||||
//import java.util.concurrent.CompletableFuture;
|
|
||||||
//import java.util.concurrent.CompletionStage;
|
|
||||||
//import java.util.concurrent.TimeUnit;
|
|
||||||
//
|
|
||||||
///**
|
|
||||||
// * Интеграционные тесты авторификации по JSON-протоколу через WebSocket.
|
|
||||||
// *
|
|
||||||
// * Требуется запущенный сервер на:
|
|
||||||
// * ws://localhost:7070/ws
|
|
||||||
// *
|
|
||||||
// * Операции:
|
|
||||||
// * - AddUser
|
|
||||||
// * - AuthChallenge
|
|
||||||
// * - CreateAuthSession
|
|
||||||
// * - RefreshSession
|
|
||||||
// * - CloseActiveSession
|
|
||||||
// * - (позже) ListSessions
|
|
||||||
// */
|
|
||||||
//public class AuthWebSocketIntegrationTest {
|
|
||||||
//
|
|
||||||
// private static final String WS_URI = "ws://localhost:7070/ws";
|
|
||||||
// private static final ObjectMapper JSON = new ObjectMapper();
|
|
||||||
// private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
|
|
||||||
//
|
|
||||||
// /** Таймаут ожидания ответа от сервера в каждом helper-е (секунд). */
|
|
||||||
// private static final long WS_TIMEOUT_SEC = 15;
|
|
||||||
//
|
|
||||||
// // ========================================================================
|
|
||||||
// // DTO
|
|
||||||
// // ========================================================================
|
|
||||||
//
|
|
||||||
// /** Тестовый пользователь. */
|
|
||||||
// private static class TestUser {
|
|
||||||
// String login;
|
|
||||||
// long loginId;
|
|
||||||
// long bchId;
|
|
||||||
//
|
|
||||||
// byte[] loginPriv;
|
|
||||||
// byte[] devicePriv;
|
|
||||||
//
|
|
||||||
// String loginPubB64;
|
|
||||||
// String devicePubB64;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /** Токены созданной сессии. */
|
|
||||||
// private static class SessionTokens {
|
|
||||||
// String sessionId;
|
|
||||||
// String sessionPwd;
|
|
||||||
// String storagePwd;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ========================================================================
|
|
||||||
// // ВСПОМОГАТЕЛЬНЫЕ МЕТОДЫ
|
|
||||||
// // ========================================================================
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Создать тестового пользователя с уникальным логином и ключами Ed25519.
|
|
||||||
// */
|
|
||||||
// private TestUser createRandomUser() {
|
|
||||||
// TestUser u = new TestUser();
|
|
||||||
//
|
|
||||||
// long ts = System.currentTimeMillis();
|
|
||||||
// u.login = "anya_test_auth_scenario_" + ts;
|
|
||||||
// u.loginId = ts; // просто уникальный long
|
|
||||||
// u.bchId = ts % 1_000_000; // что-нибудь псевдоуникальное
|
|
||||||
//
|
|
||||||
// // Генерируем ключи детерминированно от логина — чтобы AddUser и Auth совпадали
|
|
||||||
// u.loginPriv = Ed25519Util.generatePrivateKeyFromString("login-key-" + u.login);
|
|
||||||
// u.devicePriv = Ed25519Util.generatePrivateKeyFromString("device-key-" + u.login);
|
|
||||||
//
|
|
||||||
// byte[] loginPub = Ed25519Util.derivePublicKey(u.loginPriv);
|
|
||||||
// byte[] devicePub = Ed25519Util.derivePublicKey(u.devicePriv);
|
|
||||||
//
|
|
||||||
// u.loginPubB64 = Ed25519Util.keyToBase64(loginPub);
|
|
||||||
// u.devicePubB64 = Ed25519Util.keyToBase64(devicePub);
|
|
||||||
//
|
|
||||||
// return u;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Универсальный helper для одношаговой операции (AddUser, RefreshSession и т.п.).
|
|
||||||
// * Открывает WebSocket, отправляет JSON, ждёт один ответ.
|
|
||||||
// *
|
|
||||||
// * @param requestJson JSON-запрос
|
|
||||||
// * @param label ярлык для логов
|
|
||||||
// * @return JsonNode root ответа
|
|
||||||
// */
|
|
||||||
// private JsonNode callSingleJsonOp(String requestJson, String label) throws Exception {
|
|
||||||
// System.out.println();
|
|
||||||
// System.out.println("===== " + label + " =====");
|
|
||||||
// System.out.println("📤 Request:");
|
|
||||||
// System.out.println(requestJson);
|
|
||||||
//
|
|
||||||
// CompletableFuture<JsonNode> future = new CompletableFuture<>();
|
|
||||||
//
|
|
||||||
// HTTP_CLIENT.newWebSocketBuilder()
|
|
||||||
// .connectTimeout(Duration.ofSeconds(WS_TIMEOUT_SEC))
|
|
||||||
// .buildAsync(URI.create(WS_URI), new WebSocket.Listener() {
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onOpen(WebSocket webSocket) {
|
|
||||||
// webSocket.request(1);
|
|
||||||
// webSocket.sendText(requestJson, true);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public CompletionStage<?> onText(WebSocket webSocket,
|
|
||||||
// CharSequence data,
|
|
||||||
// boolean last) {
|
|
||||||
// String msg = data.toString();
|
|
||||||
// System.out.println("📥 Response:");
|
|
||||||
// System.out.println(msg);
|
|
||||||
// System.out.println("----------------------------------------");
|
|
||||||
// try {
|
|
||||||
// JsonNode root = JSON.readTree(msg);
|
|
||||||
// future.complete(root);
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// future.completeExceptionally(e);
|
|
||||||
// } finally {
|
|
||||||
// try {
|
|
||||||
// webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "test done");
|
|
||||||
// } catch (Exception ignored) {
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// webSocket.request(1);
|
|
||||||
// return CompletableFuture.completedFuture(null);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onError(WebSocket webSocket, Throwable error) {
|
|
||||||
// if (!future.isDone()) {
|
|
||||||
// future.completeExceptionally(error);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public CompletionStage<?> onClose(WebSocket webSocket,
|
|
||||||
// int statusCode,
|
|
||||||
// String reason) {
|
|
||||||
// if (!future.isDone()) {
|
|
||||||
// future.completeExceptionally(new IllegalStateException(
|
|
||||||
// "WebSocket closed before response. code=" + statusCode + ", reason=" + reason));
|
|
||||||
// }
|
|
||||||
// return CompletableFuture.completedFuture(null);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// return future.get(WS_TIMEOUT_SEC, TimeUnit.SECONDS);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Helper для двухшагового сценария:
|
|
||||||
// * 1) AuthChallenge
|
|
||||||
// * 2) CreateAuthSession
|
|
||||||
// */
|
|
||||||
// private SessionTokens createSessionForUser(TestUser user, String logPrefix) throws Exception {
|
|
||||||
// System.out.println();
|
|
||||||
// System.out.println("===== " + logPrefix + " createSessionForUser: " + user.login + " =====");
|
|
||||||
//
|
|
||||||
// CompletableFuture<SessionTokens> resultFuture = new CompletableFuture<>();
|
|
||||||
//
|
|
||||||
// HTTP_CLIENT.newWebSocketBuilder()
|
|
||||||
// .connectTimeout(Duration.ofSeconds(WS_TIMEOUT_SEC))
|
|
||||||
// .buildAsync(URI.create(WS_URI), new WebSocket.Listener() {
|
|
||||||
//
|
|
||||||
// int step = 0;
|
|
||||||
// WebSocket ws;
|
|
||||||
// String currentAuthNonce;
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onOpen(WebSocket webSocket) {
|
|
||||||
// this.ws = webSocket;
|
|
||||||
// webSocket.request(1);
|
|
||||||
//
|
|
||||||
// // Шаг 1: AuthChallenge
|
|
||||||
// String reqId = "auth-challenge-" + UUID.randomUUID();
|
|
||||||
// String json = """
|
|
||||||
// {
|
|
||||||
// "op": "AuthChallenge",
|
|
||||||
// "requestId": "%s",
|
|
||||||
// "payload": {
|
|
||||||
// "login": "%s"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// """.formatted(reqId, user.login);
|
|
||||||
//
|
|
||||||
// System.out.println();
|
|
||||||
// System.out.println(logPrefix + " 📤 [STEP1 AuthChallenge] Request:");
|
|
||||||
// System.out.println(json);
|
|
||||||
// webSocket.sendText(json, true);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public CompletionStage<?> onText(WebSocket webSocket,
|
|
||||||
// CharSequence data,
|
|
||||||
// boolean last) {
|
|
||||||
// String msg = data.toString();
|
|
||||||
// System.out.println();
|
|
||||||
// System.out.println(logPrefix + " 📥 Incoming message (step " + step + "):");
|
|
||||||
// System.out.println(msg);
|
|
||||||
// System.out.println("--------------------------------------------------");
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// if (step == 0) {
|
|
||||||
// // Ответ на AuthChallenge
|
|
||||||
// JsonNode root = JSON.readTree(msg);
|
|
||||||
// int status = root.path("status").asInt();
|
|
||||||
// if (status != 200) {
|
|
||||||
// String code = root.path("payload").path("code").asText();
|
|
||||||
// String message = root.path("payload").path("message").asText();
|
|
||||||
// throw new IllegalStateException(
|
|
||||||
// "AuthChallenge failed: status=" + status +
|
|
||||||
// ", code=" + code +
|
|
||||||
// ", message=" + message);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// currentAuthNonce = root.path("payload").path("authNonce").asText(null);
|
|
||||||
// if (currentAuthNonce == null || currentAuthNonce.isBlank()) {
|
|
||||||
// throw new IllegalStateException("AuthChallenge: empty authNonce in response");
|
|
||||||
// }
|
|
||||||
// System.out.println(logPrefix + " 🔑 authNonce = " + currentAuthNonce);
|
|
||||||
//
|
|
||||||
// // Шаг 2: CreateAuthSession
|
|
||||||
// long timeMs = System.currentTimeMillis();
|
|
||||||
// String signatureB64 = buildAuthorificatedSignature(
|
|
||||||
// user.devicePriv,
|
|
||||||
// currentAuthNonce,
|
|
||||||
// timeMs
|
|
||||||
// );
|
|
||||||
// String storagePwd = generateFakeStoragePwd();
|
|
||||||
//
|
|
||||||
// String reqId2 = "create-session-" + UUID.randomUUID();
|
|
||||||
// String json2 = """
|
|
||||||
// {
|
|
||||||
// "op": "CreateAuthSession",
|
|
||||||
// "requestId": "%s",
|
|
||||||
// "payload": {
|
|
||||||
// "storagePwd": "%s",
|
|
||||||
// "timeMs": %d,
|
|
||||||
// "signatureB64": "%s",
|
|
||||||
// "clientInfo": "AuthTestClient/1.0"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// """.formatted(
|
|
||||||
// reqId2,
|
|
||||||
// storagePwd,
|
|
||||||
// timeMs,
|
|
||||||
// signatureB64
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// System.out.println();
|
|
||||||
// System.out.println(logPrefix + " 📤 [STEP2 CreateAuthSession] Request:");
|
|
||||||
// System.out.println(json2);
|
|
||||||
//
|
|
||||||
// step = 1;
|
|
||||||
// webSocket.sendText(json2, true);
|
|
||||||
// } else if (step == 1) {
|
|
||||||
// // Ответ на CreateAuthSession
|
|
||||||
// JsonNode root = JSON.readTree(msg);
|
|
||||||
// int status = root.path("status").asInt();
|
|
||||||
// if (status != 200) {
|
|
||||||
// String code = root.path("payload").path("code").asText();
|
|
||||||
// String message = root.path("payload").path("message").asText();
|
|
||||||
// throw new IllegalStateException(
|
|
||||||
// "CreateAuthSession failed: status=" + status +
|
|
||||||
// ", code=" + code +
|
|
||||||
// ", message=" + message);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// String sessionId = root.path("payload").path("sessionId").asText(null);
|
|
||||||
// String sessionPwd = root.path("payload").path("sessionPwd").asText(null);
|
|
||||||
// if (sessionId == null || sessionPwd == null) {
|
|
||||||
// throw new IllegalStateException("CreateAuthSession: sessionId or sessionPwd is null");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// SessionTokens tokens = new SessionTokens();
|
|
||||||
// tokens.sessionId = sessionId;
|
|
||||||
// tokens.sessionPwd = sessionPwd;
|
|
||||||
// tokens.storagePwd = null; // мы знаем, какой отправляли, при желании можно сохранить
|
|
||||||
//
|
|
||||||
// System.out.println(logPrefix + " 🆔 sessionId = " + sessionId);
|
|
||||||
// System.out.println(logPrefix + " 🔐 sessionPwd = " + sessionPwd);
|
|
||||||
//
|
|
||||||
// resultFuture.complete(tokens);
|
|
||||||
//
|
|
||||||
// try {
|
|
||||||
// webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "session created");
|
|
||||||
// } catch (Exception ignored) {
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// // Лишние сообщения — считаем ошибкой
|
|
||||||
// throw new IllegalStateException("Unexpected extra message on step=" + step);
|
|
||||||
// }
|
|
||||||
// } catch (Exception ex) {
|
|
||||||
// if (!resultFuture.isDone()) {
|
|
||||||
// resultFuture.completeExceptionally(ex);
|
|
||||||
// }
|
|
||||||
// try {
|
|
||||||
// webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "error in test");
|
|
||||||
// } catch (Exception ignored) {
|
|
||||||
// }
|
|
||||||
// } finally {
|
|
||||||
// webSocket.request(1);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return CompletableFuture.completedFuture(null);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onError(WebSocket webSocket, Throwable error) {
|
|
||||||
// System.out.println(logPrefix + " ❌ WebSocket error: " + error.getMessage());
|
|
||||||
// if (!resultFuture.isDone()) {
|
|
||||||
// resultFuture.completeExceptionally(error);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public CompletionStage<?> onClose(WebSocket webSocket,
|
|
||||||
// int statusCode,
|
|
||||||
// String reason) {
|
|
||||||
// System.out.println(logPrefix + " 🔚 WebSocket closed. code=" + statusCode + ", reason=" + reason);
|
|
||||||
// if (!resultFuture.isDone()) {
|
|
||||||
// resultFuture.completeExceptionally(
|
|
||||||
// new IllegalStateException("Closed before session tokens were received"));
|
|
||||||
// }
|
|
||||||
// return CompletableFuture.completedFuture(null);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// // ждём результат или ошибку
|
|
||||||
// return resultFuture.get(WS_TIMEOUT_SEC, TimeUnit.SECONDS);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Собрать подпись над строкой "AUTHORIFICATED:" + timeMs + authNonce
|
|
||||||
// * приватным ключом устройства.
|
|
||||||
// */
|
|
||||||
// private String buildAuthorificatedSignature(byte[] devicePrivKey,
|
|
||||||
// String authNonce,
|
|
||||||
// long timeMs) {
|
|
||||||
// String preimageStr = "AUTHORIFICATED:" + timeMs + authNonce;
|
|
||||||
// byte[] preimage = preimageStr.getBytes(StandardCharsets.UTF_8);
|
|
||||||
// byte[] sig = Ed25519Util.sign(preimage, devicePrivKey);
|
|
||||||
// return Base64.getEncoder().encodeToString(sig);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /** Просто base64 от 32 байт 1..32 — для storagePwd. */
|
|
||||||
// private String generateFakeStoragePwd() {
|
|
||||||
// byte[] data = new byte[32];
|
|
||||||
// for (int i = 0; i < data.length; i++) {
|
|
||||||
// data[i] = (byte) (i + 1);
|
|
||||||
// }
|
|
||||||
// return Base64.getEncoder().encodeToString(data);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // ========================================================================
|
|
||||||
// // ТЕСТЫ
|
|
||||||
// // ========================================================================
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 1) Регистрируем пользователя через AddUser
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// void addUser_shouldSucceed() throws Exception {
|
|
||||||
// TestUser user = createRandomUser();
|
|
||||||
//
|
|
||||||
// String reqId = "add-" + UUID.randomUUID();
|
|
||||||
// String json = """
|
|
||||||
// {
|
|
||||||
// "op": "AddUser",
|
|
||||||
// "requestId": "%s",
|
|
||||||
// "payload": {
|
|
||||||
// "login": "%s",
|
|
||||||
// "loginId": %d,
|
|
||||||
// "bchId": %d,
|
|
||||||
// "loginKey": "%s",
|
|
||||||
// "deviceKey": "%s",
|
|
||||||
// "bchLimit": 1000000
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// """.formatted(
|
|
||||||
// reqId,
|
|
||||||
// user.login,
|
|
||||||
// user.loginId,
|
|
||||||
// user.bchId,
|
|
||||||
// user.loginPubB64,
|
|
||||||
// user.devicePubB64
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// JsonNode resp = callSingleJsonOp(json, "TEST addUser_shouldSucceed");
|
|
||||||
// int status = resp.path("status").asInt();
|
|
||||||
// String code = resp.path("payload").path("code").asText(null);
|
|
||||||
//
|
|
||||||
// Assertions.assertEquals(
|
|
||||||
// 200,
|
|
||||||
// status,
|
|
||||||
// "Ожидался status=200 при AddUser, но сервер вернул: status=" + status + ", code=" + code
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// System.out.println("✅ [TEST] AddUser прошёл успешно для login=" + user.login);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 2) Создать пользователя и сразу сделать CreateAuthSession (AuthChallenge + CreateAuthSession).
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// void createSession_flow_shouldReturnSessionIdAndPwd() throws Exception {
|
|
||||||
// TestUser user = createRandomUser();
|
|
||||||
//
|
|
||||||
// // Сначала регистрируем пользователя
|
|
||||||
// {
|
|
||||||
// String reqId = "add-" + UUID.randomUUID();
|
|
||||||
// String json = """
|
|
||||||
// {
|
|
||||||
// "op": "AddUser",
|
|
||||||
// "requestId": "%s",
|
|
||||||
// "payload": {
|
|
||||||
// "login": "%s",
|
|
||||||
// "loginId": %d,
|
|
||||||
// "bchId": %d,
|
|
||||||
// "loginKey": "%s",
|
|
||||||
// "deviceKey": "%s",
|
|
||||||
// "bchLimit": 1000000
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// """.formatted(
|
|
||||||
// reqId,
|
|
||||||
// user.login,
|
|
||||||
// user.loginId,
|
|
||||||
// user.bchId,
|
|
||||||
// user.loginPubB64,
|
|
||||||
// user.devicePubB64
|
|
||||||
// );
|
|
||||||
// JsonNode resp = callSingleJsonOp(json, "TEST createSession_flow / AddUser");
|
|
||||||
// int status = resp.path("status").asInt();
|
|
||||||
// Assertions.assertEquals(200, status, "AddUser должен вернуть 200");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// SessionTokens tokens = createSessionForUser(user, "[createSession_flow]");
|
|
||||||
// Assertions.assertNotNull(tokens.sessionId, "sessionId не должен быть null");
|
|
||||||
// Assertions.assertNotNull(tokens.sessionPwd, "sessionPwd не должен быть null");
|
|
||||||
//
|
|
||||||
// System.out.println("✅ [TEST] Сессия успешно создана: sessionId=" + tokens.sessionId);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * 3) Сценарий с двумя сессиями (упрощённая версия):
|
|
||||||
// * - создаём пользователя
|
|
||||||
// * - создаём первую сессию
|
|
||||||
// * - создаём вторую сессию
|
|
||||||
// * - убеждаемся, что sessionId разные
|
|
||||||
// *
|
|
||||||
// * Полный цикл с ListSessions / CloseActiveSession можно будет нарастить поверх
|
|
||||||
// * этого теста, когда добавим JSON-обработчик Net_ListSessions.
|
|
||||||
// */
|
|
||||||
// @Test
|
|
||||||
// void fullTwoSessionLifecycleScenario() throws Exception {
|
|
||||||
// TestUser user = createRandomUser();
|
|
||||||
//
|
|
||||||
// // 1) AddUser
|
|
||||||
// String reqId = "add-" + UUID.randomUUID();
|
|
||||||
// String jsonAdd = """
|
|
||||||
// {
|
|
||||||
// "op": "AddUser",
|
|
||||||
// "requestId": "%s",
|
|
||||||
// "payload": {
|
|
||||||
// "login": "%s",
|
|
||||||
// "loginId": %d,
|
|
||||||
// "bchId": %d,
|
|
||||||
// "loginKey": "%s",
|
|
||||||
// "deviceKey": "%s",
|
|
||||||
// "bchLimit": 1000000
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// """.formatted(
|
|
||||||
// reqId,
|
|
||||||
// user.login,
|
|
||||||
// user.loginId,
|
|
||||||
// user.bchId,
|
|
||||||
// user.loginPubB64,
|
|
||||||
// user.devicePubB64
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// JsonNode addResp = callSingleJsonOp(jsonAdd, "SCENARIO fullTwoSessionLifecycle / AddUser");
|
|
||||||
// int addStatus = addResp.path("status").asInt();
|
|
||||||
// Assertions.assertEquals(200, addStatus, "AddUser должен вернуть 200");
|
|
||||||
//
|
|
||||||
// System.out.println("✅ [SC] Пользователь создан: " + user.login);
|
|
||||||
//
|
|
||||||
// // 2) Первая сессия
|
|
||||||
// SessionTokens s1 = createSessionForUser(user, "[SC S1]");
|
|
||||||
// // 3) Вторая сессия
|
|
||||||
// SessionTokens s2 = createSessionForUser(user, "[SC S2]");
|
|
||||||
//
|
|
||||||
// Assertions.assertNotEquals(
|
|
||||||
// s1.sessionId,
|
|
||||||
// s2.sessionId,
|
|
||||||
// "Первая и вторая сессия должны иметь разные sessionId"
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// System.out.println();
|
|
||||||
// System.out.println("✅ [SC] Полный сценарий (упрощённый) успешно отработал:");
|
|
||||||
// System.out.println(" session1 = " + s1.sessionId);
|
|
||||||
// System.out.println(" session2 = " + s2.sessionId);
|
|
||||||
//
|
|
||||||
// System.out.println("\nℹ️ ListSessions / CloseActiveSession / повторные проверки можно будет добавить, " +
|
|
||||||
// "когда JSON-обработчик Net_ListSessions будет реализован на сервере.");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@ -8,38 +8,96 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
|
|
||||||
public class AddUserIT {
|
public class AddUserIT {
|
||||||
|
|
||||||
|
// ANSI цвета (работает в большинстве терминалов)
|
||||||
|
private static final String R = "\u001B[0m";
|
||||||
|
private static final String G = "\u001B[32m";
|
||||||
|
private static final String Y = "\u001B[33m";
|
||||||
|
private static final String RED = "\u001B[31m";
|
||||||
|
private static final String C = "\u001B[36m";
|
||||||
|
|
||||||
|
private static void line() {
|
||||||
|
System.out.println(C + "------------------------------------------------------------" + R);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void title(String s) {
|
||||||
|
System.out.println(C + "\n============================================================" + R);
|
||||||
|
System.out.println(C + s + R);
|
||||||
|
System.out.println(C + "============================================================\n" + R);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ok(String s) {
|
||||||
|
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);
|
||||||
|
System.out.println(RED + "****************************************************************" + R);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void addUser_shouldReturn200_orAlreadyExists() {
|
void addUser_shouldReturn200_orAlreadyExists() {
|
||||||
|
title("AddUserIT: проверка добавления пользователя (200 OK) или 'уже существует' (409 USER_ALREADY_EXISTS)");
|
||||||
|
System.out.println("Ожидание:");
|
||||||
|
System.out.println(" - сервер принимает AddUser и возвращает:");
|
||||||
|
System.out.println(" * 200 (пользователь создан/добавлен)");
|
||||||
|
System.out.println(" * либо 409 + payload.code=USER_ALREADY_EXISTS (если уже есть)\n");
|
||||||
|
|
||||||
try (WsTestClient client = new WsTestClient(TestConfig.WS_URI)) {
|
try (WsTestClient client = new WsTestClient(TestConfig.WS_URI)) {
|
||||||
|
|
||||||
String reqId = "it-adduser-1";
|
String reqId = "it-adduser-1";
|
||||||
String reqJson = JsonBuilders.addUser(reqId);
|
String reqJson = JsonBuilders.addUser(reqId);
|
||||||
|
|
||||||
TestLog.section("AddUserIT: AddUser");
|
System.out.println("📤 Отправляем AddUser запрос:");
|
||||||
TestLog.req("AddUser requestId=" + reqId, reqJson);
|
System.out.println(reqJson);
|
||||||
|
line();
|
||||||
|
|
||||||
String resp = client.request(reqId, reqJson, Duration.ofSeconds(5));
|
String resp = client.request(reqId, reqJson, Duration.ofSeconds(5));
|
||||||
TestLog.resp("AddUser responseId=" + reqId, resp);
|
|
||||||
|
System.out.println("📥 Ответ сервера:");
|
||||||
|
System.out.println(resp);
|
||||||
|
line();
|
||||||
|
|
||||||
int st = JsonParsers.status(resp);
|
int st = JsonParsers.status(resp);
|
||||||
|
System.out.println("ℹ️ status=" + st);
|
||||||
|
|
||||||
boolean created = (st == 200);
|
boolean created = (st == 200);
|
||||||
boolean already = (st == 409);
|
boolean already = (st == 409);
|
||||||
|
|
||||||
if (already) {
|
if (already) {
|
||||||
|
// ВАЖНО: payload.code (не errorCode)
|
||||||
String code = JsonParsers.errorCode(resp);
|
String code = JsonParsers.errorCode(resp);
|
||||||
// если сервер кладет code в payload.code — парсер должен это поддерживать (см. ниже)
|
|
||||||
assertEquals("USER_ALREADY_EXISTS", code,
|
System.out.println("ℹ️ server_code=" + code);
|
||||||
"Expected errorCode=USER_ALREADY_EXISTS, but got: " + code + ", resp=" + resp);
|
|
||||||
|
// Если 409 пришёл, требуем понятный code
|
||||||
|
try {
|
||||||
|
assertEquals("USER_ALREADY_EXISTS", code,
|
||||||
|
"Expected code=USER_ALREADY_EXISTS, but got: " + code + ", resp=" + resp);
|
||||||
|
ok("409 получен корректно: USER_ALREADY_EXISTS");
|
||||||
|
} catch (AssertionError ae) {
|
||||||
|
boom("409 получен, но code не тот. " + ae.getMessage());
|
||||||
|
throw ae;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (created) {
|
if (created) {
|
||||||
System.out.println("✅ AddUser: создан/добавлен (status=200)");
|
ok("ТЕСТ ПРОЙДЕН: AddUser создан/добавлен (status=200)");
|
||||||
} else if (already) {
|
} else if (already) {
|
||||||
System.out.println("✅ AddUser: уже есть в системе (status=409, USER_ALREADY_EXISTS)");
|
ok("ТЕСТ ПРОЙДЕН: AddUser уже есть в системе (status=409, USER_ALREADY_EXISTS)");
|
||||||
} else {
|
} else {
|
||||||
|
boom("Неожиданный status=" + st + ", resp=" + resp);
|
||||||
fail("❌ AddUser: неожиданный status=" + st + ", resp=" + resp);
|
fail("❌ AddUser: неожиданный status=" + st + ", resp=" + resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (AssertionError | RuntimeException e) {
|
||||||
|
// чтобы “красным” было видно даже если Gradle/IDE печатает стек отдельно
|
||||||
|
boom("ТЕСТ УПАЛ: AddUserIT. Причина: " + e.getMessage());
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10,15 +10,91 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
|
|
||||||
public class SessionsIT {
|
public class SessionsIT {
|
||||||
|
|
||||||
|
// ANSI цвета
|
||||||
|
private static final String R = "\u001B[0m";
|
||||||
|
private static final String G = "\u001B[32m";
|
||||||
|
private static final String Y = "\u001B[33m";
|
||||||
|
private static final String RED = "\u001B[31m";
|
||||||
|
private static final String C = "\u001B[36m";
|
||||||
|
|
||||||
|
private static void line() {
|
||||||
|
System.out.println(C + "------------------------------------------------------------" + R);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void title(String s) {
|
||||||
|
System.out.println(C + "\n============================================================" + R);
|
||||||
|
System.out.println(C + s + R);
|
||||||
|
System.out.println(C + "============================================================\n" + R);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void stepTitle(String s) {
|
||||||
|
System.out.println(C + "\n-------------------- " + s + " --------------------" + R);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ok(String s) {
|
||||||
|
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);
|
||||||
|
System.out.println(RED + "****************************************************************" + R);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void send(String op, String json) {
|
||||||
|
System.out.println("📤 [" + op + "] Request JSON:");
|
||||||
|
System.out.println(json);
|
||||||
|
line();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void recv(String op, String json) {
|
||||||
|
System.out.println("📥 [" + op + "] Response JSON:");
|
||||||
|
System.out.println(json);
|
||||||
|
line();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assert200(String op, String resp) {
|
||||||
|
int st = JsonParsers.status(resp);
|
||||||
|
try {
|
||||||
|
assertEquals(200, st, op + ": expected status=200, but got=" + st + ", resp=" + resp);
|
||||||
|
ok(op + ": status=200");
|
||||||
|
} catch (AssertionError ae) {
|
||||||
|
boom(op + ": ожидали 200, но получили " + st);
|
||||||
|
throw ae;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void ensureUserExists() {
|
static void ensureUserExists() {
|
||||||
|
title("SessionsIT (BeforeAll): предусловие — пользователь должен существовать (AddUser: 200 или 409)");
|
||||||
|
|
||||||
try (WsTestClient client = new WsTestClient(TestConfig.WS_URI)) {
|
try (WsTestClient client = new WsTestClient(TestConfig.WS_URI)) {
|
||||||
String reqId = "it-adduser-beforeall";
|
String reqId = "it-adduser-beforeall";
|
||||||
String resp = client.request(reqId, JsonBuilders.addUser(reqId), Duration.ofSeconds(5));
|
String reqJson = JsonBuilders.addUser(reqId);
|
||||||
|
|
||||||
|
send("AddUser(BeforeAll)", reqJson);
|
||||||
|
String resp = client.request(reqId, reqJson, Duration.ofSeconds(5));
|
||||||
|
recv("AddUser(BeforeAll)", resp);
|
||||||
|
|
||||||
int st = JsonParsers.status(resp);
|
int st = JsonParsers.status(resp);
|
||||||
|
|
||||||
// 200 или "уже есть" — ок
|
// 200 или "уже есть" — ок
|
||||||
if (!(st == 200 || st == 409)) {
|
if (st == 200) {
|
||||||
|
ok("BeforeAll: пользователь создан/добавлен (status=200)");
|
||||||
|
} else if (st == 409) {
|
||||||
|
String code = JsonParsers.errorCode(resp);
|
||||||
|
if ("USER_ALREADY_EXISTS".equals(code)) {
|
||||||
|
ok("BeforeAll: пользователь уже есть (status=409, USER_ALREADY_EXISTS)");
|
||||||
|
} else {
|
||||||
|
boom("BeforeAll: status=409, но code неожиданный: " + code);
|
||||||
|
fail("User precondition failed. status=409, code=" + code + ", resp=" + resp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
boom("BeforeAll: предусловие не выполнено. status=" + st);
|
||||||
fail("User precondition failed. status=" + st + ", resp=" + resp);
|
fail("User precondition failed. status=" + st + ", resp=" + resp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,141 +102,246 @@ public class SessionsIT {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sessions_flow_shouldCreateListRefreshCloseCorrectly() {
|
void sessions_flow_shouldCreateListRefreshCloseCorrectly() {
|
||||||
|
title("SessionsIT: полный сценарий сессий (создать 2, проверить list, refresh/close, проверить очистку)");
|
||||||
|
System.out.println("Ожидание сценария:");
|
||||||
|
System.out.println(" 1) Создаём SESSION1 через AuthChallenge + CreateAuthSession");
|
||||||
|
System.out.println(" 2) Создаём SESSION2 и делаем ListSessions внутри неё (AUTH_STATUS_USER) → должны быть SESSION1 и SESSION2");
|
||||||
|
System.out.println(" 3) Делаем ListSessions в AUTH_IN_PROGRESS (подпись по nonce) → должны быть SESSION1 и SESSION2");
|
||||||
|
System.out.println(" 4) Refresh SESSION1 (входим в AUTH_STATUS_USER) и Close SESSION2");
|
||||||
|
System.out.println(" 5) Проверяем ListSessions (AUTH_IN_PROGRESS) → осталась только SESSION1");
|
||||||
|
System.out.println(" 6) Закрываем SESSION1 в AUTH_IN_PROGRESS");
|
||||||
|
System.out.println(" 7) Проверяем ListSessions → пусто\n");
|
||||||
|
|
||||||
String s1Id, s1Pwd;
|
String s1Id, s1Pwd;
|
||||||
String s2Id, s2Pwd;
|
String s2Id, s2Pwd;
|
||||||
|
|
||||||
// --- create session1 ---
|
try {
|
||||||
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
// --- create session1 ---
|
||||||
String r1 = "it-auth-1";
|
stepTitle("ШАГ 1: создать SESSION1 (AuthChallenge -> CreateAuthSession)");
|
||||||
String resp1 = c.request(r1, JsonBuilders.authChallenge(r1), Duration.ofSeconds(5));
|
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
||||||
assertEquals(200, JsonParsers.status(resp1));
|
String r1 = "it-auth-1";
|
||||||
String nonce = JsonParsers.authNonce(resp1);
|
String req1 = JsonBuilders.authChallenge(r1);
|
||||||
assertNotNull(nonce);
|
send("AuthChallenge#1", req1);
|
||||||
|
String resp1 = c.request(r1, req1, Duration.ofSeconds(5));
|
||||||
|
recv("AuthChallenge#1", resp1);
|
||||||
|
|
||||||
String r2 = "it-create-1";
|
assert200("AuthChallenge#1", resp1);
|
||||||
String storagePwd = TestConfig.fakeStoragePwd();
|
String nonce = JsonParsers.authNonce(resp1);
|
||||||
String resp2 = c.request(r2, JsonBuilders.createAuthSession(r2, nonce, storagePwd), Duration.ofSeconds(5));
|
assertNotNull(nonce, "AuthChallenge#1: nonce must not be null");
|
||||||
assertEquals(200, JsonParsers.status(resp2));
|
ok("AuthChallenge#1: authNonce получен: " + nonce);
|
||||||
|
|
||||||
s1Id = JsonParsers.sessionId(resp2);
|
String r2 = "it-create-1";
|
||||||
s1Pwd = JsonParsers.sessionPwd(resp2);
|
String storagePwd = TestConfig.fakeStoragePwd();
|
||||||
assertNotNull(s1Id);
|
String req2 = JsonBuilders.createAuthSession(r2, nonce, storagePwd);
|
||||||
assertNotNull(s1Pwd);
|
send("CreateAuthSession#1", req2);
|
||||||
}
|
String resp2 = c.request(r2, req2, Duration.ofSeconds(5));
|
||||||
|
recv("CreateAuthSession#1", resp2);
|
||||||
|
|
||||||
// --- create session2 and list inside (AUTH_STATUS_USER) ---
|
assert200("CreateAuthSession#1", resp2);
|
||||||
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
|
||||||
String r1 = "it-auth-2";
|
|
||||||
String resp1 = c.request(r1, JsonBuilders.authChallenge(r1), Duration.ofSeconds(5));
|
|
||||||
assertEquals(200, JsonParsers.status(resp1));
|
|
||||||
String nonce = JsonParsers.authNonce(resp1);
|
|
||||||
assertNotNull(nonce);
|
|
||||||
|
|
||||||
String r2 = "it-create-2";
|
s1Id = JsonParsers.sessionId(resp2);
|
||||||
String resp2 = c.request(r2, JsonBuilders.createAuthSession(r2, nonce, TestConfig.fakeStoragePwd()), Duration.ofSeconds(5));
|
s1Pwd = JsonParsers.sessionPwd(resp2);
|
||||||
assertEquals(200, JsonParsers.status(resp2));
|
assertNotNull(s1Id, "CreateAuthSession#1: sessionId must not be null");
|
||||||
|
assertNotNull(s1Pwd, "CreateAuthSession#1: sessionPwd must not be null");
|
||||||
|
ok("SESSION1 получена: sessionId=" + s1Id + ", sessionPwd=[получен]");
|
||||||
|
}
|
||||||
|
|
||||||
s2Id = JsonParsers.sessionId(resp2);
|
// --- create session2 and list inside (AUTH_STATUS_USER) ---
|
||||||
s2Pwd = JsonParsers.sessionPwd(resp2);
|
stepTitle("ШАГ 2: создать SESSION2 и ListSessions внутри неё (AUTH_STATUS_USER) → должны быть SESSION1+SESSION2");
|
||||||
assertNotNull(s2Id);
|
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
||||||
assertNotNull(s2Pwd);
|
String r1 = "it-auth-2";
|
||||||
|
String req1 = JsonBuilders.authChallenge(r1);
|
||||||
|
send("AuthChallenge#2", req1);
|
||||||
|
String resp1 = c.request(r1, req1, Duration.ofSeconds(5));
|
||||||
|
recv("AuthChallenge#2", resp1);
|
||||||
|
|
||||||
// list inside session2 (у тебя это AUTH_STATUS_USER без подписи)
|
assert200("AuthChallenge#2", resp1);
|
||||||
String r3 = "it-list-in-session2";
|
String nonce = JsonParsers.authNonce(resp1);
|
||||||
String resp3 = c.request(r3, JsonBuilders.listSessions(r3, 0L, ""), Duration.ofSeconds(5));
|
assertNotNull(nonce);
|
||||||
assertEquals(200, JsonParsers.status(resp3));
|
ok("AuthChallenge#2: authNonce получен: " + nonce);
|
||||||
List<String> ids = JsonParsers.sessionIds(resp3);
|
|
||||||
|
|
||||||
assertTrue(ids.contains(s1Id), "Must contain session1");
|
String r2 = "it-create-2";
|
||||||
assertTrue(ids.contains(s2Id), "Must contain session2");
|
String req2 = JsonBuilders.createAuthSession(r2, nonce, TestConfig.fakeStoragePwd());
|
||||||
}
|
send("CreateAuthSession#2", req2);
|
||||||
|
String resp2 = c.request(r2, req2, Duration.ofSeconds(5));
|
||||||
|
recv("CreateAuthSession#2", resp2);
|
||||||
|
|
||||||
// --- list in AUTH_IN_PROGRESS (подпись по nonce) ---
|
assert200("CreateAuthSession#2", resp2);
|
||||||
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
|
||||||
String r1 = "it-auth-list";
|
|
||||||
String resp1 = c.request(r1, JsonBuilders.authChallenge(r1), Duration.ofSeconds(5));
|
|
||||||
assertEquals(200, JsonParsers.status(resp1));
|
|
||||||
String nonce = JsonParsers.authNonce(resp1);
|
|
||||||
assertNotNull(nonce);
|
|
||||||
|
|
||||||
long timeMs = System.currentTimeMillis();
|
s2Id = JsonParsers.sessionId(resp2);
|
||||||
String sig = JsonBuilders.signAuthorificated(nonce, timeMs);
|
s2Pwd = JsonParsers.sessionPwd(resp2);
|
||||||
|
assertNotNull(s2Id);
|
||||||
|
assertNotNull(s2Pwd);
|
||||||
|
ok("SESSION2 получена: sessionId=" + s2Id + ", sessionPwd=[получен]");
|
||||||
|
|
||||||
String r2 = "it-list-auth-in-progress";
|
// list inside session2 (у тебя это AUTH_STATUS_USER без подписи)
|
||||||
String resp2 = c.request(r2, JsonBuilders.listSessions(r2, timeMs, sig), Duration.ofSeconds(5));
|
String r3 = "it-list-in-session2";
|
||||||
assertEquals(200, JsonParsers.status(resp2));
|
String req3 = JsonBuilders.listSessions(r3, 0L, "");
|
||||||
|
send("ListSessions(in SESSION2)", req3);
|
||||||
|
String resp3 = c.request(r3, req3, Duration.ofSeconds(5));
|
||||||
|
recv("ListSessions(in SESSION2)", resp3);
|
||||||
|
|
||||||
List<String> ids = JsonParsers.sessionIds(resp2);
|
assert200("ListSessions(in SESSION2)", resp3);
|
||||||
assertTrue(ids.contains(s1Id));
|
List<String> ids = JsonParsers.sessionIds(resp3);
|
||||||
assertTrue(ids.contains(s2Id));
|
ok("ListSessions(in SESSION2): sessions=" + ids);
|
||||||
}
|
|
||||||
|
|
||||||
// --- refresh session1 and close session2 (from session1) ---
|
assertTrue(ids.contains(s1Id), "Must contain session1");
|
||||||
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
assertTrue(ids.contains(s2Id), "Must contain session2");
|
||||||
|
ok("Проверка OK: список содержит SESSION1 и SESSION2");
|
||||||
|
}
|
||||||
|
|
||||||
String r1 = "it-refresh-s1";
|
// --- list in AUTH_IN_PROGRESS (подпись по nonce) ---
|
||||||
String resp1 = c.request(r1, JsonBuilders.refreshSession(r1, s1Id, s1Pwd), Duration.ofSeconds(5));
|
stepTitle("ШАГ 3: ListSessions в AUTH_IN_PROGRESS (nonce+signature) → должны быть SESSION1+SESSION2");
|
||||||
assertEquals(200, JsonParsers.status(resp1));
|
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
||||||
assertNotNull(JsonParsers.storagePwd(resp1));
|
String r1 = "it-auth-list";
|
||||||
|
String req1 = JsonBuilders.authChallenge(r1);
|
||||||
|
send("AuthChallenge(list)", req1);
|
||||||
|
String resp1 = c.request(r1, req1, Duration.ofSeconds(5));
|
||||||
|
recv("AuthChallenge(list)", resp1);
|
||||||
|
|
||||||
String r2 = "it-close-s2";
|
assert200("AuthChallenge(list)", resp1);
|
||||||
String resp2 = c.request(r2, JsonBuilders.closeActiveSession(r2, s2Id, 0L, ""), Duration.ofSeconds(5));
|
String nonce = JsonParsers.authNonce(resp1);
|
||||||
assertEquals(200, JsonParsers.status(resp2));
|
assertNotNull(nonce);
|
||||||
}
|
ok("AuthChallenge(list): authNonce=" + nonce);
|
||||||
|
|
||||||
// --- verify only session1 remains (AUTH_IN_PROGRESS list) ---
|
long timeMs = System.currentTimeMillis();
|
||||||
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
String sig = JsonBuilders.signAuthorificated(nonce, timeMs);
|
||||||
String r1 = "it-auth-list2";
|
ok("Подпись для AUTH_IN_PROGRESS: timeMs=" + timeMs + ", signatureB64=[сгенерирована]");
|
||||||
String resp1 = c.request(r1, JsonBuilders.authChallenge(r1), Duration.ofSeconds(5));
|
|
||||||
assertEquals(200, JsonParsers.status(resp1));
|
|
||||||
String nonce = JsonParsers.authNonce(resp1);
|
|
||||||
assertNotNull(nonce);
|
|
||||||
|
|
||||||
long timeMs = System.currentTimeMillis();
|
String r2 = "it-list-auth-in-progress";
|
||||||
String sig = JsonBuilders.signAuthorificated(nonce, timeMs);
|
String req2 = JsonBuilders.listSessions(r2, timeMs, sig);
|
||||||
|
send("ListSessions(AUTH_IN_PROGRESS)", req2);
|
||||||
|
String resp2 = c.request(r2, req2, Duration.ofSeconds(5));
|
||||||
|
recv("ListSessions(AUTH_IN_PROGRESS)", resp2);
|
||||||
|
|
||||||
String r2 = "it-list-after-close-s2";
|
assert200("ListSessions(AUTH_IN_PROGRESS)", resp2);
|
||||||
String resp2 = c.request(r2, JsonBuilders.listSessions(r2, timeMs, sig), Duration.ofSeconds(5));
|
|
||||||
assertEquals(200, JsonParsers.status(resp2));
|
|
||||||
|
|
||||||
List<String> ids = JsonParsers.sessionIds(resp2);
|
List<String> ids = JsonParsers.sessionIds(resp2);
|
||||||
assertTrue(ids.contains(s1Id));
|
ok("ListSessions(AUTH_IN_PROGRESS): sessions=" + ids);
|
||||||
assertFalse(ids.contains(s2Id));
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- close session1 in AUTH_IN_PROGRESS ---
|
assertTrue(ids.contains(s1Id));
|
||||||
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
assertTrue(ids.contains(s2Id));
|
||||||
String r1 = "it-auth-close-s1";
|
ok("Проверка OK: AUTH_IN_PROGRESS список содержит SESSION1 и SESSION2");
|
||||||
String resp1 = c.request(r1, JsonBuilders.authChallenge(r1), Duration.ofSeconds(5));
|
}
|
||||||
assertEquals(200, JsonParsers.status(resp1));
|
|
||||||
String nonce = JsonParsers.authNonce(resp1);
|
|
||||||
assertNotNull(nonce);
|
|
||||||
|
|
||||||
long timeMs = System.currentTimeMillis();
|
// --- refresh session1 and close session2 (from session1) ---
|
||||||
String sig = JsonBuilders.signAuthorificated(nonce, timeMs);
|
stepTitle("ШАГ 4: Refresh SESSION1 (входим) и Close SESSION2 (из SESSION1)");
|
||||||
|
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
||||||
|
|
||||||
String r2 = "it-close-s1";
|
String r1 = "it-refresh-s1";
|
||||||
String resp2 = c.request(r2, JsonBuilders.closeActiveSession(r2, s1Id, timeMs, sig), Duration.ofSeconds(5));
|
String req1 = JsonBuilders.refreshSession(r1, s1Id, s1Pwd);
|
||||||
assertEquals(200, JsonParsers.status(resp2));
|
send("RefreshSession(SESSION1)", req1);
|
||||||
}
|
String resp1 = c.request(r1, req1, Duration.ofSeconds(5));
|
||||||
|
recv("RefreshSession(SESSION1)", resp1);
|
||||||
|
|
||||||
// --- verify empty list ---
|
assert200("RefreshSession(SESSION1)", resp1);
|
||||||
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
assertNotNull(JsonParsers.storagePwd(resp1));
|
||||||
String r1 = "it-auth-list-empty";
|
ok("RefreshSession: storagePwd получен");
|
||||||
String resp1 = c.request(r1, JsonBuilders.authChallenge(r1), Duration.ofSeconds(5));
|
|
||||||
assertEquals(200, JsonParsers.status(resp1));
|
|
||||||
String nonce = JsonParsers.authNonce(resp1);
|
|
||||||
assertNotNull(nonce);
|
|
||||||
|
|
||||||
long timeMs = System.currentTimeMillis();
|
String r2 = "it-close-s2";
|
||||||
String sig = JsonBuilders.signAuthorificated(nonce, timeMs);
|
String req2 = JsonBuilders.closeActiveSession(r2, s2Id, 0L, "");
|
||||||
|
send("CloseActiveSession(SESSION2)", req2);
|
||||||
|
String resp2 = c.request(r2, req2, Duration.ofSeconds(5));
|
||||||
|
recv("CloseActiveSession(SESSION2)", resp2);
|
||||||
|
|
||||||
String r2 = "it-list-empty";
|
assert200("CloseActiveSession(SESSION2)", resp2);
|
||||||
String resp2 = c.request(r2, JsonBuilders.listSessions(r2, timeMs, sig), Duration.ofSeconds(5));
|
ok("SESSION2 закрыта");
|
||||||
assertEquals(200, JsonParsers.status(resp2));
|
}
|
||||||
|
|
||||||
List<String> ids = JsonParsers.sessionIds(resp2);
|
// --- verify only session1 remains (AUTH_IN_PROGRESS list) ---
|
||||||
assertTrue(ids.isEmpty(), "Sessions must be empty");
|
stepTitle("ШАГ 5: ListSessions(AUTH_IN_PROGRESS) → должна остаться только SESSION1");
|
||||||
|
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
||||||
|
String r1 = "it-auth-list2";
|
||||||
|
String req1 = JsonBuilders.authChallenge(r1);
|
||||||
|
send("AuthChallenge(list2)", req1);
|
||||||
|
String resp1 = c.request(r1, req1, Duration.ofSeconds(5));
|
||||||
|
recv("AuthChallenge(list2)", resp1);
|
||||||
|
|
||||||
|
assert200("AuthChallenge(list2)", resp1);
|
||||||
|
String nonce = JsonParsers.authNonce(resp1);
|
||||||
|
assertNotNull(nonce);
|
||||||
|
|
||||||
|
long timeMs = System.currentTimeMillis();
|
||||||
|
String sig = JsonBuilders.signAuthorificated(nonce, timeMs);
|
||||||
|
|
||||||
|
String r2 = "it-list-after-close-s2";
|
||||||
|
String req2 = JsonBuilders.listSessions(r2, timeMs, sig);
|
||||||
|
send("ListSessions(after close S2)", req2);
|
||||||
|
String resp2 = c.request(r2, req2, Duration.ofSeconds(5));
|
||||||
|
recv("ListSessions(after close S2)", resp2);
|
||||||
|
|
||||||
|
assert200("ListSessions(after close S2)", resp2);
|
||||||
|
|
||||||
|
List<String> ids = JsonParsers.sessionIds(resp2);
|
||||||
|
ok("ListSessions(after close S2): sessions=" + ids);
|
||||||
|
|
||||||
|
assertTrue(ids.contains(s1Id));
|
||||||
|
assertFalse(ids.contains(s2Id));
|
||||||
|
ok("Проверка OK: осталась только SESSION1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- close session1 in AUTH_IN_PROGRESS ---
|
||||||
|
stepTitle("ШАГ 6: Close SESSION1 в AUTH_IN_PROGRESS");
|
||||||
|
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
||||||
|
String r1 = "it-auth-close-s1";
|
||||||
|
String req1 = JsonBuilders.authChallenge(r1);
|
||||||
|
send("AuthChallenge(close S1)", req1);
|
||||||
|
String resp1 = c.request(r1, req1, Duration.ofSeconds(5));
|
||||||
|
recv("AuthChallenge(close S1)", resp1);
|
||||||
|
|
||||||
|
assert200("AuthChallenge(close S1)", resp1);
|
||||||
|
String nonce = JsonParsers.authNonce(resp1);
|
||||||
|
assertNotNull(nonce);
|
||||||
|
|
||||||
|
long timeMs = System.currentTimeMillis();
|
||||||
|
String sig = JsonBuilders.signAuthorificated(nonce, timeMs);
|
||||||
|
|
||||||
|
String r2 = "it-close-s1";
|
||||||
|
String req2 = JsonBuilders.closeActiveSession(r2, s1Id, timeMs, sig);
|
||||||
|
send("CloseActiveSession(SESSION1)", req2);
|
||||||
|
String resp2 = c.request(r2, req2, Duration.ofSeconds(5));
|
||||||
|
recv("CloseActiveSession(SESSION1)", resp2);
|
||||||
|
|
||||||
|
assert200("CloseActiveSession(SESSION1)", resp2);
|
||||||
|
ok("SESSION1 закрыта");
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- verify empty list ---
|
||||||
|
stepTitle("ШАГ 7: ListSessions(AUTH_IN_PROGRESS) → ожидаем пустой список");
|
||||||
|
try (WsTestClient c = new WsTestClient(TestConfig.WS_URI)) {
|
||||||
|
String r1 = "it-auth-list-empty";
|
||||||
|
String req1 = JsonBuilders.authChallenge(r1);
|
||||||
|
send("AuthChallenge(list empty)", req1);
|
||||||
|
String resp1 = c.request(r1, req1, Duration.ofSeconds(5));
|
||||||
|
recv("AuthChallenge(list empty)", resp1);
|
||||||
|
|
||||||
|
assert200("AuthChallenge(list empty)", resp1);
|
||||||
|
String nonce = JsonParsers.authNonce(resp1);
|
||||||
|
assertNotNull(nonce);
|
||||||
|
|
||||||
|
long timeMs = System.currentTimeMillis();
|
||||||
|
String sig = JsonBuilders.signAuthorificated(nonce, timeMs);
|
||||||
|
|
||||||
|
String r2 = "it-list-empty";
|
||||||
|
String req2 = JsonBuilders.listSessions(r2, timeMs, sig);
|
||||||
|
send("ListSessions(empty)", req2);
|
||||||
|
String resp2 = c.request(r2, req2, Duration.ofSeconds(5));
|
||||||
|
recv("ListSessions(empty)", resp2);
|
||||||
|
|
||||||
|
assert200("ListSessions(empty)", resp2);
|
||||||
|
|
||||||
|
List<String> ids = JsonParsers.sessionIds(resp2);
|
||||||
|
ok("ListSessions(empty): sessions=" + ids);
|
||||||
|
|
||||||
|
assertTrue(ids.isEmpty(), "Sessions must be empty");
|
||||||
|
ok("Проверка OK: список пуст");
|
||||||
|
}
|
||||||
|
|
||||||
|
ok("ТЕСТ ПРОЙДЕН ЦЕЛИКОМ: SessionsIT (весь сценарий сессий выполнен успешно)");
|
||||||
|
|
||||||
|
} catch (AssertionError | RuntimeException e) {
|
||||||
|
boom("ТЕСТ УПАЛ: SessionsIT. Причина: " + e.getMessage());
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
32
src/test/java/test/it/TestLog.java
Normal file
32
src/test/java/test/it/TestLog.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package test.it;
|
||||||
|
|
||||||
|
public final class TestLog {
|
||||||
|
private TestLog(){}
|
||||||
|
|
||||||
|
// включается так: ./gradlew test -Dit.verbose=true
|
||||||
|
public static final boolean VERBOSE = true; //Boolean.parseBoolean(System.getProperty("it.verbose", "false"));
|
||||||
|
|
||||||
|
public static void info(String s) {
|
||||||
|
if (VERBOSE) System.out.println(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void section(String title) {
|
||||||
|
if (!VERBOSE) return;
|
||||||
|
System.out.println("\n\n==================================================");
|
||||||
|
System.out.println(title);
|
||||||
|
System.out.println("==================================================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void req(String title, String json) {
|
||||||
|
if (!VERBOSE) return;
|
||||||
|
System.out.println("\n📤 " + title);
|
||||||
|
System.out.println(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resp(String title, String json) {
|
||||||
|
if (!VERBOSE) return;
|
||||||
|
System.out.println("\n📥 " + title);
|
||||||
|
System.out.println(json);
|
||||||
|
System.out.println("-----------------------------------------------------");
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user