#include <balancer/kernel/module/ssl_props.h>
#include <balancer/kernel/ssl/sslja3.h>

#include <library/cpp/testing/unittest/registar.h>

Y_UNIT_TEST_SUITE(TJa3Test) {
    Y_UNIT_TEST(CorrectCiphersList) {
        TVector<ui8> ciphers({1, 0, 0, 1});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, ciphers, emptyInt, empty, empty, empty, empty, empty, empty, empty, empty);

        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja3HeaderValue(), "0,256-1,,,");
    }

    Y_UNIT_TEST(IncorrectCiphersList) {
        TVector<ui8> ciphers({0, 1, 1});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, ciphers, emptyInt, empty, empty, empty, empty, empty, empty, empty, empty);

        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja3HeaderValue(), "0,1-256,,,");
    }

    Y_UNIT_TEST(CorrectEmptyEllipticCurvesList) {
        TVector<ui8> curvers({0, 0});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, curvers, empty, empty, empty, empty, empty, empty, empty);

        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja3HeaderValue(), "0,,,,");
    }


    Y_UNIT_TEST(CorrectEllipticCurvesList) {
        TVector<ui8> curvers({0, 0, 1, 0, 0, 1});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, curvers, empty, empty, empty, empty, empty, empty, empty);

        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja3HeaderValue(), "0,,,256-1,");
    }

    Y_UNIT_TEST(IncorrectEllipticCurvesList) {
        TVector<ui8> curvers({0, 0, 0, 0, 1});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, curvers, empty, empty, empty, empty, empty, empty, empty);

        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja3HeaderValue(), "0,,,0-256,");
    }

    Y_UNIT_TEST(CorrectSignatureAlgorithms) {
        TVector<ui8> signatureAlgorithms({0, 6, 0, 0, 1, 1, 10, 10});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, signatureAlgorithms, signatureAlgorithms, empty, empty, empty, empty);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), "0-257,0-257,,,,");
    }

    Y_UNIT_TEST(IncorrectSignatureAlgorithms) {
        TVector<ui8> signatureAlgorithms({0, 4, 0, 0, 1});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, signatureAlgorithms, signatureAlgorithms, empty, empty, empty, empty);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), "0-256,0-256,,,,");
    }

    Y_UNIT_TEST(CorrectSupportedVersions) {
        TVector<ui8> supportedVersions({8, 0, 10, 20, 10, 10, 11, 10, 10});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, empty, empty, supportedVersions, empty, empty, empty);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), ",,10-5130-2571,,,");
    }

    Y_UNIT_TEST(IncorrectSupportedVersions) {
        TVector<ui8> supportedVersions({6, 0, 10, 20, 10, 10});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, empty, empty, supportedVersions, empty, empty, empty);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), ",,10-5130-2560,,,");
    }

    Y_UNIT_TEST(CorrectApplicationLayerProtocolNegotiation) {
        TVector<ui8> protocols({0, 21, 2, 'h', '2', 8, 'i', 'g', 'n', 'o', 'r', 'e', '/', 'a', 8, 'h', 't', 't', 'p', '/', '1', '.', '1'});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, empty, empty, empty, protocols, empty, empty);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), ",,,h2-http/1.1,,");
    }

    Y_UNIT_TEST(IncorrectApplicationLayerProtocolNegotiation) {
        TVector<ui8> protocols({0, 10, 2, 'h', '2', 80, 'h', 't', 't', 'p', '/', '1', '.', '1', ','});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, empty, empty, empty, protocols, empty, empty);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), ",,,h2-http/1.1,,");
    }

    Y_UNIT_TEST(CorrectKeyShare) {
        TVector<ui8> keyShare({0, 17, 0, 101, 0, 4, 101, 102, 103, 104, 10, 10, 0, 1, 1, 0, 102, 0, 5, 101, 102, 103, 104, 105});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, empty, empty, empty, empty, keyShare, empty);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), ",,,,101-102,");
    }

    Y_UNIT_TEST(IncorrectKeyShare) {
        TVector<ui8> keyShare({10, 170, 0, 101, 0, 4, 101, 102, 103, 104, 0, 102, 10, 50, 101, 102, 103, 104, 105});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, empty, empty, empty, empty, keyShare, empty);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), ",,,,101-102,");
    }

    Y_UNIT_TEST(CorrectPskKeyExchangeModes) {
        TVector<ui8> exchangeModes({3, 1, 2, 11});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, empty, empty, empty, empty, empty, exchangeModes);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), ",,,,,1-2");
    }

    Y_UNIT_TEST(IncorrectPskKeyExchangeModes) {
        TVector<ui8> exchangeModes({20, 1, 2});
        TVector<ui8> empty({});
        TVector<int> emptyInt({});

        NSrvKernel::TSslJa3Data data(0, empty, emptyInt, empty, empty, empty, empty, empty, empty, empty, exchangeModes);
        NSrvKernel::TSslJa3 ja3(&data);
        UNIT_ASSERT_VALUES_EQUAL(ja3.Ja4HeaderValue(), ",,,,,1-2");
    }
}
