package be.iminds.ilabt.jfed.lowlevel.api.test;

import be.iminds.ilabt.jfed.log.Logger;
import be.iminds.ilabt.jfed.lowlevel.*;
import be.iminds.ilabt.jfed.lowlevel.api.AbstractFederationApi2;
import be.iminds.ilabt.jfed.lowlevel.api.FederationMemberAuthorityApi2;
import be.iminds.ilabt.jfed.lowlevel.api.ProtogeniSliceAuthority;
import be.iminds.ilabt.jfed.lowlevel.connection.JFedConnectionProvider;
import be.iminds.ilabt.jfed.lowlevel.connection.SfaConnection;
import be.iminds.ilabt.jfed.preferences.JFedPreferences;
import be.iminds.ilabt.jfed.util.GeniUrn;
import be.iminds.ilabt.jfed.util.SSHKeyHelper;
import be.iminds.ilabt.jfed.util.TargetAuthority;

import javax.inject.Inject;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * TestFederationMemberAuthority2
 */
public class TestFederationMemberAuthority2 extends AbstractFederationApi2Test {
    @Inject
    public TestFederationMemberAuthority2(Logger logger, TargetAuthority testedAuthority, GeniUserProvider geniUserProvider, JFedConnectionProvider connectionProvider, TestbedInfoSource testbedInfoSource, JFedPreferences jFedPreferences) {
        super(logger, testedAuthority, geniUserProvider, connectionProvider, testbedInfoSource, jFedPreferences);
    }

    public String getTestDescription() {
        return "Test Federation API Member Authority version 2";
    }

    private FederationMemberAuthorityApi2 ma;


    private GeniUrn testUserUrn;

    public SfaConnection getConnection() throws JFedException {
        return (SfaConnection) connectionProvider.getConnectionByAuthority(user, testedAuthority.getServerToConnect(),
                new ApiInfo.Api(ApiInfo.ApiName.GENI_CH_MA, 2));
    }

    final List<String> memberDefaultFieldNames = new ArrayList<>();
    List<AbstractFederationApi2.GetVersionResult.FieldInfo> memberDefaultFields =
            new ArrayList<>();
    final List<String> keyDefaultFieldNames = new ArrayList<>();
    List<AbstractFederationApi2.GetVersionResult.FieldInfo> keyDefaultFields =
            new ArrayList<>();

    public void setUp() {

        ma = new FederationMemberAuthorityApi2(logger, jFedPreferences);
        ma.setHandleMalformedReplies(false); //throw exceptions instead of trying to recover from malformed replies

        testUserUrn = GeniUrn.parse(user.getUserUrnString());
        assertNotNull(testUserUrn, "Error in test user urn: " + user.getUserUrnString());

        memberDefaultFields = ma.getMinimumFields("MEMBER");
        keyDefaultFields = ma.getMinimumFields("KEY");
        for (AbstractFederationApi2.GetVersionResult.FieldInfo fi : memberDefaultFields)
            memberDefaultFieldNames.add(fi.getName());
        for (AbstractFederationApi2.GetVersionResult.FieldInfo fi : keyDefaultFields)
            keyDefaultFieldNames.add(fi.getName());
    }

    private boolean hasKeyService = false;

    @Test(groups = {"getversion"})
    public void getVersion() throws JFedException {
        AbstractFederationApi2.FederationApiReply<AbstractFederationApi2.GetVersionResult> reply =
                ma.getVersion(getConnection());
        checkGetVersion(reply, ma, true);

        Map<String, Object> htRes = (Map<String, Object>) reply.getRawValue();
        List services = assertMapContainsList(htRes, "SERVICES");

        if (services != null) {
            hasKeyService = services.contains("KEY");
        }
    }

    AnyCredential maTestUserCredential;
    List<AnyCredential> maTestUserCredentialList;

    @Test(softDepends = {"getVersion"}, groups = {"get_credential"})
    public void getTestUserCredential() throws JFedException {
        AbstractFederationApi2.FederationApiReply<List<AnyCredential>> reply =
                ma.getCredentials(getConnection(), new ArrayList<>(), testUserUrn, null);
        checkCorrectnessXmlRpcResult(reply);
        assertTrue(reply.getGeniResponseCode().isSuccess(),
                "The tested call did not return code 0 (success), instead it returned " + reply.getGeniResponseCode());

        Object[] rawVal = assertInstanceOf(reply.getRawValue(), Object[].class,
                "The get_credential call should return an array (List) of dictionaries, instead it returned a " +
                        reply.getRawValue().getClass().getName()
        );;
        for (Object credO : rawVal)
            assertInstanceOf(credO, Map.class,
                    "The get_credential call should return an array containing dictionaries, " +
                            "instead one of the values in the array is a " + credO.getClass().getName()
            );

        List<AnyCredential> testUserCreds = reply.getValue();
        assertNotNull(testUserCreds, "no credential returned");

        assertEquals(testUserCreds.size(), rawVal.length, "Error in jFed: raw credential list length (" +
                testUserCreds.size() + ") differs from converted credential list length (" + rawVal.length + ")");

        assertNotEmpty(testUserCreds,
                "empty list of credentials returned. Expecting a list with credentials, but got  " +
                        (reply.getRawValue() == null ?
                                "null" :
                                (reply.getRawValue() instanceof Object[] ?
                                        ("a list: " + reply.getRawValue()) :
                                        ("something of class:" + reply.getRawValue().getClass().getName())
                                )
                        )
        );
        maTestUserCredentialList = new ArrayList<>(testUserCreds);
        maTestUserCredential = testUserCreds.get(0);
    }

    AnyCredential testUserCredential;
    List<AnyCredential> testUserCredentialList;

    @Test(softDepends = {"getTestUserCredential"}, groups = {
            "get_credential"}, description = "Get A Credential for the test user. If the MA get_credential call did not work, this will try to fall back to the old PROTOGENI_SA API.")
    public void retrieveCredentialSomehow() throws JFedException {
        if (maTestUserCredentialList != null && maTestUserCredential != null) {
            testUserCredential = maTestUserCredential;
            testUserCredentialList = maTestUserCredentialList;
        } else {
            if (!ApiInfo.hasService(user.getUserAuthorityServer(), ApiInfo.ApiName.PROTOGENI_SA, 1)) {
                errorFatal("The Uniform Federation API Member Authority get_credential call failed to provide a credential. additionally, the test user authority does not have a PROTOGENI_SA available as fallback. => Cannot retrieve a credential for the test user.");
            } else {
                note("The Uniform Federation API Member Authority get_credential call failed to provide a credential: Falling back to the PROTOGENI_SA API to retrieve a credential for the remaining tests.");
                SfaConnection protogeniSaCon =
                        (SfaConnection) connectionProvider.getConnectionByAuthority(user,
                                user.getUserAuthorityServer(), new ApiInfo.Api(ApiInfo.ApiName.PROTOGENI_SA, 1));
                ProtogeniSliceAuthority protogeniSa = new ProtogeniSliceAuthority(logger, jFedPreferences);

                ProtogeniSliceAuthority.SliceAuthorityReply<AnyCredential> pgSaReply =
                        protogeniSa.getCredential(protogeniSaCon);
                assertTrue(pgSaReply.getGeniResponseCode().isSuccess());
                AnyCredential pgCred = pgSaReply.getValue();

                assertNotNull(pgCred, "no credential returned by protogeni SA");
                testUserCredentialList = new ArrayList<>();
                testUserCredentialList.add(pgCred);
                testUserCredential = pgCred;
            }
        }
    }

    private void checkMemberLookupResult(AbstractFederationApi2.FederationApiReply<FederationMemberAuthorityApi2.MemberInfoList> reply, List<String> expectedFieldNames, List<String> excludedFieldNames) {
        setErrorsFatal();

        checkCorrectnessXmlRpcResult(reply);
        checkLookupCorrectness(reply);
        Map<String, Map<String, Object>> raw =
                (Map<String, Map<String, Object>>) reply.getRawValue();

        // FederationMemberAuthorityApi2.MemberInfoList lookupRes = reply.getValue();
        if (raw == null) {
            warn("lookup result is null. This is either due to receiving an incorrect result (will fail later in this test in that case), or due a a bug in the API client implementation");
            return;
        }
//        assertNotNull(lookupRes, "lookup result is null");
//        assertNotNull(testUserUrn, "bug in test (testUserUrn is null)");
//
//        assertTrue(lookupRes.size() > 0, "Lookup result is empty for own urn: "+testUserUrn.getValue());

//        Map<String, Map<String, String>> raw = lookupRes.getRaw();
        errorNonFatalIfNot(raw.size() == 1, "lookup must return one user, but it returned " + raw.size());

        Map<String, Object> rawUser = raw.get(testUserUrn.getValue());
        errorNonFatalIfNot(rawUser != null, "lookup must return requested test user (" + testUserUrn.getValue() + ") user.");

        assert rawUser != null;
        String rawUrn = (String) rawUser.get("MEMBER_URN"); //check that if this users has a member urn, it matches.
        if (rawUrn != null && !Objects.equals(testUserUrn.getValue(), rawUrn))
            errorNonFatal("lookup must return requested test user (" + testUserUrn.getValue() + ") user, and it did, however its returned MEMBER_URN entry is not matching: " + rawUrn);

//        for (int i = 0; i < raw.size(); i++) {
//            Map<String, String> memberInfo = raw.get(i);
        for (Map.Entry<String, Map<String, Object>> e : raw.entrySet()) {
            Map<String, Object> memberInfo = e.getValue();
            for (String fieldName : expectedFieldNames) {
                if (!memberInfo.containsKey(fieldName))
                    errorNonFatal("returned result does not contain field: \"" + fieldName + "\"");
            }
            for (String fieldName : excludedFieldNames) {
                if (memberInfo.containsKey(fieldName))
                    errorNonFatal("returned result contains unexpected field: \"" + fieldName + "\"");
            }
        }
    }


    @Test(hardDepends = {"retrieveCredentialSomehow"}, groups = {"lookup_member"})
    public void lookupMemberInfoNoFilter() throws JFedException {
        lookupMemberInfoXFilterHelper(null, false);
    }

    @Test(hardDepends = {"retrieveCredentialSomehow"}, groups = {"lookup_member"})
    public void lookupMemberInfoEmptyFilter() throws JFedException {
        List<String> filter = new ArrayList<>();
        note("this test calls a lookup with an EMPTY filter specified. So there is a filter, is just is empty. " +
                "This test is expecting NO fields to be returned.");
        lookupMemberInfoXFilterHelper(filter, false);
    }

    @Test(hardDepends = {"retrieveCredentialSomehow"}, groups = {"lookup_member"})
    public void lookupMemberInfoNoFilterWithMatchList() throws JFedException {
        lookupMemberInfoXFilterHelper(null, true);
    }

    @Test(hardDepends = {"retrieveCredentialSomehow"}, groups = {"lookup_member"})
    public void lookupMemberInfoEmptyFilterWithMatchList() throws JFedException {
        List<String> filter = new ArrayList<>();
        note("this test calls a lookup with an EMPTY filter specified. So there is a filter, is just is empty. " +
                "This test is expecting NO fields to be returned.");
        lookupMemberInfoXFilterHelper(filter, true);
    }

    public void lookupMemberInfoXFilterHelper(List<String> filter, boolean makeMatchList /*if true, make match a list instead of a single item*/) throws JFedException {
        Map<String, Object> match = new HashMap<>();

        if (makeMatchList) {
            List<Object> v = new ArrayList<>();
            v.add(testUserUrn.getValue());
            match.put("MEMBER_URN", v);
        } else
            match.put("MEMBER_URN", testUserUrn.getValue());

        note("looking up member by MEMBER_URN: " + testUserUrn.getValue() + " with filter: " + filter);
        AbstractFederationApi2.FederationApiReply<FederationMemberAuthorityApi2.MemberInfoList> reply =
                ma.lookupMember(getConnection(), testUserCredentialList, match, filter, null);
        checkCorrectnessXmlRpcResult(reply);

        assertTrue(reply.getGeniResponseCode().isSuccess(), "The tested call did not return code 0 (success), instead it returned " + reply.getGeniResponseCode());

        List<String> expectedFieldNames = new ArrayList<>();
        List<String> excludedFieldNames = new ArrayList<>();
        for (AbstractFederationApi2.GetVersionResult.FieldInfo fi : memberDefaultFields)
            if (/*fi.getProtect().equals(AbstractFederationApi2.GetVersionResult.FieldInfo.Protect.PUBLIC) &&*/ (filter == null || filter.contains(fi.getName())))
                expectedFieldNames.add(fi.getName());
            else
                excludedFieldNames.add(fi.getName());
        if (filter != null && filter.isEmpty())
            note("Empty filter provided, so expecting no fields to be returned: excludedFieldNames=" + excludedFieldNames);
        if (filter == null)
            note("No filter provided, so expecting all fields to be returned: " + expectedFieldNames);
        if (filter != null && !filter.isEmpty())
            note("filter provided, so expecting only these fields to be returned: " + filter + " while none of these fields should be returned: " + excludedFieldNames);
        checkMemberLookupResult(reply, expectedFieldNames, excludedFieldNames);
    }


    @Test(hardDepends = {"retrieveCredentialSomehow"}, softDepends = {
            "lookupMemberInfoEmptyFilter"}, groups = {"lookup_member"})
    public void lookupPublicMemberInfoFiltered() throws JFedException {
        List<String> filter = new ArrayList<>();
        filter.add("MEMBER_UID");

        lookupMemberInfoXFilterHelper(filter, false);
    }

    @Test(hardDepends = {"retrieveCredentialSomehow"}, softDepends = {"lookupMemberInfoEmptyFilter"}, groups = {
            "lookup_member"})
    public void lookupIdentifyingMemberInfoFiltered() throws JFedException {
        List<String> filter = new ArrayList<>();
        filter.add("MEMBER_EMAIL");
        filter.add("MEMBER_FIRSTNAME");

        lookupMemberInfoXFilterHelper(filter, false);
    }

    @Test(hardDepends = {"retrieveCredentialSomehow"}, softDepends = {
            "lookupMemberInfoEmptyFilter"}, groups = {"lookup_member"})
    public void lookupPublicMemberInfoFilteredWithMatchList() throws JFedException {
        List<String> filter = new ArrayList<>();
        filter.add("MEMBER_UID");

        lookupMemberInfoXFilterHelper(filter, true);
    }

    @Test(hardDepends = {"retrieveCredentialSomehow"}, softDepends = {"lookupMemberInfoEmptyFilter"}, groups = {
            "lookup_member"})
    public void lookupIdentifyingMemberInfoFilteredWithMatchList() throws JFedException {
        List<String> filter = new ArrayList<>();
        filter.add("MEMBER_EMAIL");
        filter.add("MEMBER_FIRSTNAME");

        lookupMemberInfoXFilterHelper(filter, true);
    }


    /////////////////////////////////////////////////////// KEYS ///////////////////////////////////////////////////////

    private SSHKeyHelper sshKeyHelper;
    private Map<String, Object> keyCreationDetails;
    private static final String initialKeyDescription = "Randomly generated public key used for automated testing";
    private String keyId;

    @Test(hardDepends = {"retrieveCredentialSomehow"}, softDepends = {
            //softDeps just for order (KEY methods after MEMBER methods):
            "lookupMemberInfoNoFilter",
            "lookupMemberInfoEmptyFilter",
            "lookupPublicMemberInfoFiltered",
            "lookupIdentifyingMemberInfoFiltered"}, groups = {"key"})
    public void createKey() throws JFedException, NoSuchAlgorithmException {
        if (!hasKeyService) skip("No KEY service advertised in get_version");

        sshKeyHelper = new SSHKeyHelper();

        Map<String, String> fields = new HashMap<>();
        fields.put("KEY_MEMBER", user.getUserUrnString());
        fields.put("KEY_PUBLIC", sshKeyHelper.getSshPublicKeyString());
        fields.put("KEY_DESCRIPTION", initialKeyDescription);
        fields.put("KEY_TYPE", "openssh");

        AbstractFederationApi2.FederationApiReply<FederationMemberAuthorityApi2.MemberKeyInfo> reply =
                ma.createKey(getConnection(), testUserCredentialList, testUserUrn, fields, null);
        assertTrue(reply.getGeniResponseCode().isSuccess(), "The tested call did not return code 0 (success), instead it returned " + reply.getGeniResponseCode());

        Object rawValue = reply.getXmlRpcCallDetailsWithCodeValueError().getResultValueObject();
        assertNotNull(rawValue, "The call did not return a value object");
        assertInstanceOf(rawValue, Map.class, "The call did not return a dictionary");
        Map rawValueHt = (Map) rawValue;
        for (Object key : rawValueHt.keySet()) {
            assertInstanceOf(key, String.class, "One of the dictionary keys in the result value is not a String: class=" + key.getClass().getName() + " value=" + key);
            Object v = rawValueHt.get(key);
            if (Objects.equals(key, "KEY_ID") && !(v instanceof String))
                errorNonFatal("The returned KEY_ID should be a String, but it is a " + v.getClass().getName());
            if (Objects.equals(key, "KEY_DESCRIPTION") && !(v instanceof String))
                errorNonFatal("The returned KEY_DESCRIPTION should be a String, but it is a " + v.getClass().getName());
            if (!(v instanceof String))
                note("One of the dictionary values in the result value is not a String: key=" + key + " class=" + v.getClass().getName() + " value=" + v);
        }

        keyCreationDetails = assertStringObjectMap(reply.getRawValue());
        assertNotNull(keyCreationDetails, "The jFed code did not return details about the created key. (reply.getValue() == null). internal jFed error?");
        note("key details contains the following fields: " + keyCreationDetails.keySet());

        keyId = assertMapContainsNonemptyString(keyCreationDetails, "KEY_ID");
    }


    private void checkKeyLookupResult(AbstractFederationApi2.FederationApiReply<FederationMemberAuthorityApi2.MemberKeyInfoList> reply, List<String> expectedFieldNames, List<String> excludedFieldNames) {
        Map<String, Object> lookupRes = assertStringObjectMap(reply.getRawValue());
        checkCorrectnessXmlRpcResult(reply);
//        checkLookupCorrectness(reply);
        assertNotNull(lookupRes, "lookup result is null");

        assertTrue(lookupRes.size() > 0, "Lookup result is empty for keyId: " + keyId);

        errorNonFatalIfNot(lookupRes.size() == 1, "lookup must return one member with one key, but it returned " + lookupRes.size() + " members");

        Map<String, Object> key = assertStringObjectMap(lookupRes.values().stream().findAny().orElse(null));
        errorNonFatalIfNot(key != null, "lookup must return requested key (" + keyId + ") but 1 member with 1 key that was null.");

        assert key != null;

        String rawId = (String) key.get("KEY_ID"); //check that if this key has a keyId, it matches.
        if (rawId != null && !Objects.equals(keyId, rawId))
            errorNonFatal("lookup must return requested key (" + keyId + "), and it did, however its returned KEY_ID entry is not matching: " + rawId);

        for (String fieldName : expectedFieldNames) {
            if (!key.containsKey(fieldName))
                errorNonFatal("returned result does not contain field: \"" + fieldName + "\"");
        }
        for (String fieldName : excludedFieldNames) {
            if (key.containsKey(fieldName))
                errorNonFatal("returned result contains unexpected field: \"" + fieldName + "\"");
        }
    }

    @Test(hardDepends = {"createKey"}, groups = {"key"})
    public void lookupKeysNoFilter() throws JFedException {
        if (!hasKeyService) skip("No KEY service advertised in get_version");

        Map<String, String> match = new HashMap<>();

        match.put("KEY_ID", keyId);

        note("looking up key by KEY_ID: " + keyId);
        AbstractFederationApi2.FederationApiReply<FederationMemberAuthorityApi2.MemberKeyInfoList> reply =
                ma.lookupKey(getConnection(), testUserCredentialList, null/*keyId*/, match, null, null);
        checkCorrectnessXmlRpcResult(reply);

        assertTrue(reply.getGeniResponseCode().isSuccess(), "The tested call did not return code 0 (success), instead it returned " + reply.getGeniResponseCode());

        List<String> expectedFieldNames = new ArrayList<>();
        List<String> excludedFieldNames = new ArrayList<>();
        for (AbstractFederationApi2.GetVersionResult.FieldInfo fi : keyDefaultFields)
            expectedFieldNames.add(fi.getName());
        note("No filter provided, so expecting all fields to be returned: " + expectedFieldNames);
        checkKeyLookupResult(reply, expectedFieldNames, excludedFieldNames);

        Map<String, Object> rawHt = assertStringObjectMap(reply.getRawValue());
        if (rawHt != null) {
            final Map<String, Object> rawKeyInfo = assertStringObjectMap(rawHt.get(keyId));
            String desc = assertMapContainsString(rawKeyInfo, "KEY_DESCRIPTION");
            assertEquals(desc, initialKeyDescription);
        }
    }

    private static final String updatedKeyDescription =
            "Randomly generated public key used for automated testing with updated description";

    @Test(hardDepends = {"createKey"}, softDepends = {"lookupKeysNoFilter"}, groups = {"key"})
    public void updateKey() throws JFedException {
        if (!hasKeyService) skip("No KEY service advertised in get_version");

        Map<String, String> fields = new HashMap<>();
        fields.put("KEY_DESCRIPTION", updatedKeyDescription);

        AbstractFederationApi2.FederationApiReply<String> reply =
                ma.updateKey(getConnection(), testUserCredentialList, keyId, fields, null);
        checkCorrectnessXmlRpcResult(reply);

        assertTrue(reply.getGeniResponseCode().isSuccess(), "The tested call did not return code 0 (success), instead it returned " + reply.getGeniResponseCode());
    }

    @Test(hardDepends = {"updateKey"}, groups = {"key"})
    public void lookupKeysNoFilterAfterUpdate() throws JFedException {
        if (!hasKeyService) skip("No KEY service advertised in get_version");

        Map<String, String> match = new HashMap<>();
        List<String> filter = null;// new List<String>();

        match.put("KEY_ID", keyId);

        note("looking up key by KEY_ID: " + keyId);
        AbstractFederationApi2.FederationApiReply<FederationMemberAuthorityApi2.MemberKeyInfoList> reply =
                ma.lookupKey(getConnection(), testUserCredentialList, null/*keyId*/, match, null, null);
        checkCorrectnessXmlRpcResult(reply);

        assertTrue(reply.getGeniResponseCode().isSuccess(), "The tested call did not return code 0 (success), instead it returned " + reply.getGeniResponseCode());

        List<String> expectedFieldNames = new ArrayList<>();
        List<String> excludedFieldNames = new ArrayList<>();
        for (AbstractFederationApi2.GetVersionResult.FieldInfo fi : keyDefaultFields)
            expectedFieldNames.add(fi.getName());
        note("No filter provided, so expecting all fields to be returned: " + expectedFieldNames);
        checkKeyLookupResult(reply, expectedFieldNames, excludedFieldNames);

        Map<String, Object> rawHt = assertStringObjectMap(reply.getRawValue());
        if (rawHt != null) {
            final Map<String, Object> rawKeyInfo = assertStringObjectMap(rawHt.get(keyId));
            String desc = assertMapContainsString(rawKeyInfo, "KEY_DESCRIPTION");
            assertNotNull(desc);
            assertEquals(desc, updatedKeyDescription);
        }
    }

    @Test(hardDepends = {"retrieveCredentialSomehow"}, groups = {"key"}, softDepends = {"createKey",
                                                                                        "lookupKeysNoFilterAfterUpdate"}, description = "Try to delete key. Always called to ensure an attempt to delete is always made.")
    public void deleteKey() throws JFedException {
        if (!hasKeyService) skip("No KEY service advertised in get_version");
        if (keyId == null)
            skip("No key ID to delete known");

        AbstractFederationApi2.FederationApiReply<Boolean> reply =
                ma.deleteKey(getConnection(), testUserCredentialList, keyId, null);
        checkCorrectnessXmlRpcResult(reply);

        assertTrue(reply.getGeniResponseCode().isSuccess(), "delete_key unsuccessful");
    }

    @Test(hardDepends = {"deleteKey"}, groups = {"key"})
    public void lookupKeysNoFilterAfterDelete() throws JFedException {
        if (!hasKeyService) skip("No KEY service advertised in get_version");

        Map<String, String> match = new HashMap<>();
        List<String> filter = null;// new List<String>();

        match.put("KEY_ID", keyId);

        note("looking up key by KEY_ID: " + keyId);
        note("Expecting no key to be found, since we just deleted the key.");
        AbstractFederationApi2.FederationApiReply<FederationMemberAuthorityApi2.MemberKeyInfoList> reply =
                ma.lookupKey(getConnection(), testUserCredentialList, null/*keyId*/, match, null, null);
        checkCorrectnessXmlRpcResult(reply);

        assertTrue(reply.getGeniResponseCode().isSuccess(), "The tested call did not return code 0 (success), instead it returned " + reply.getGeniResponseCode());

//        checkLookupCorrectness(reply);
        FederationMemberAuthorityApi2.MemberKeyInfoList lookupRes = reply.getValue();
        assertNotNull(lookupRes);
        assertTrue(lookupRes.size() == 0, "After delete, a key was still found: " + lookupRes);
    }
}
