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.AggregateManager3;
import be.iminds.ilabt.jfed.lowlevel.api.user_spec.UserSpec;
import be.iminds.ilabt.jfed.lowlevel.connection.JFedConnectionProvider;
import be.iminds.ilabt.jfed.lowlevel.connection.SfaConnection;
import be.iminds.ilabt.jfed.lowlevel.resourceid.ResourceUrn;
import be.iminds.ilabt.jfed.preferences.JFedPreferences;
import be.iminds.ilabt.jfed.testing.base.ApiTest;
import be.iminds.ilabt.jfed.util.RFC3339Util;
import be.iminds.ilabt.jfed.util.SSHKeyHelper;
import be.iminds.ilabt.jfed.util.TargetAuthority;
import be.iminds.ilabt.jfed.util.TextUtil;

import javax.inject.Inject;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.util.*;

/**
 * TestBestEffortAMv3
 * Test if the targeted AMv3 supports best_effort on/off for:
 * - Provision
 * - PerformOperationalAction
 * - Renew
 */
public class TestBestEffortAMv3 extends ApiTest {
    private CommonAMTest commonAMTest;
    private AggregateManager3 am3;

    private Boolean createSliceIfNotExists = true;
    private Boolean reuseSliceIfExists = false;
    private Boolean disableCleanup = false;
    private Map versionRawResult = null;
    private AggregateManager3.VersionInfo versionInfo = null;
    /* Create the slices needed in the next tests. Uses SA, but not AM */
    private CommonAMTest.SliceInfo sliceP;
    private CommonAMTest.SliceInfo sliceOA;
    private CommonAMTest.SliceInfo sliceR;
    private ResourceUrn urnSliverP1;
    private List<ResourceUrn> urnSliverP2;
    private ResourceUrn urnSliverR1;
    private ResourceUrn urnSliverR2;

    @Inject
    public TestBestEffortAMv3(Logger logger, TargetAuthority testedAuthority, GeniUserProvider geniUserProvider, JFedConnectionProvider connectionProvider, TestbedInfoSource testbedInfoSource, JFedPreferences jFedPreferences) {
        super(logger, testedAuthority, geniUserProvider, connectionProvider, testbedInfoSource, jFedPreferences);
    }

    private static List<String> toStringList(String s) {
        List<String> res = new ArrayList<>();
        res.add(s);
        return res;
    }

    private static List<String> toStringList(String s1, String s2) {
        List<String> res = new ArrayList<>();
        res.add(s1);
        res.add(s2);
        return res;
    }

    /*
    *
    * For testing:
    *   - sliceP  is a slice for the Provion test
    *   - sliceOA  is a slice for the Perform Operational Action test
    *   - sliceR  is a slice for the Renew test
    *
    * */

    private static List<String> toStringList(String s1, String s2, String s3) {
        List<String> res = new ArrayList<>();
        res.add(s1);
        res.add(s2);
        res.add(s3);
        return res;
    }

    public String getTestDescription() {
        return "Many Aggregate Manager (Geni AM API v3) Tests. 2 slices and a sliver will be created during the tests. " +
                "The sliver will be deleted. This will not test ListResources.";
    }

    @Override
    public List<String> getOptConfKeys() {
        List<String> res = new ArrayList<>();

        res.add("create_slice_if_not_exists");
        res.add("reuse_slice_if_exists");
        res.add("disable_slice_cleanup"); //no deleteSliver call
        res.add("fixed_slice_name"); //uses this slice name. If not specified, will generate a slice name automatically
        res.add("fixed_project_name"); //uses this as the project/subauthority. If not specified, will choose one if needed, or not use one otherwise.
        res.add("try_to_use_project_for_slices"); //if set and no project name set, this will try to find any project for the user, and use it to create slices.

        CommonAMTest.addOptionsForNodeLoginSshProxy(res);
        CommonAMTest.addOptionsForConnectionSshProxy(res);
        CommonAMTest.addOptionsForRspecTypeVersion(res);

        return res;
    }

    public SfaConnection getAM3Connection() throws JFedException {
        return (SfaConnection) connectionProvider.getConnectionByAuthority(user, testedAuthority.getServerToConnect(), new ApiInfo.Api(ApiInfo.ApiName.GENI_AM, 3));
    }

    /**
     * Check for correctness of a AM3 XmlRpc result. Should be tested for each reply received.
     */
    public void testAM3CorrectnessXmlRpcResult(Map res) {
        Object code = res.get("code");
        Object value = res.get("value");
        Object output = res.get("output");
        assertNotNull(code, "testAM3CorrectnessXmlRpcResult code == null in " + res);
        assertNotNull(value, "testAM3CorrectnessXmlRpcResult value == null in " + res);
        assertInstanceOf(code, Map.class, "testAM3CorrectnessXmlRpcResult code is not Map in " + res);
        Map codeHt = (Map) code;
        Object genicode = codeHt.get("geni_code");
        assertNotNull(genicode, "testAM3CorrectnessXmlRpcResult code does not contain \"geni_code\" in " + res);
        assertEquals(genicode.getClass(), Integer.class, "testAM3CorrectnessXmlRpcResult code.geni_code is not int in " + res);

        int genicodevalue = (Integer) genicode;
        //output should be present if code is not 0
        if (genicodevalue != 0) {
            assertNotNull(output, "testAM3CorrectnessXmlRpcResult: while geni_code is non success (" + genicodevalue + "), output == null in " + res);
            assertEquals(output.getClass(), String.class, "testAM3CorrectnessXmlRpcResult: while geni_code is non success (" + genicodevalue + "), output is not String (it is " + output.getClass().getName() + " with value \"" + output.toString() + "\") in \"+res+\"");
        } else {
            if (output == null)
                note("testAM3CorrectnessXmlRpcResult: while geni_code is success (" + genicodevalue + "), output is ommited. This is allowed by the API.");
            if (output != null && !(output instanceof String))
                warn("testAM3CorrectnessXmlRpcResult: while geni_code is success (" + genicodevalue + "), output is not String (it is " + output.getClass().getName() + " with value \"" + output.toString() + "\"). This is allowed but not recommended by jFed.");
        }
    }

    public void setUp() {
        assertNotNull(user);
        assertNotNull(user.getUserAuthorityServer());

        commonAMTest = new CommonAMTest(this, user.getUserAuthorityServer());
        am3 = new AggregateManager3(logger, jFedPreferences);

        createSliceIfNotExists = TextUtil.objectToBoolean(getTestConfig().getProperty("create_slice_if_not_exists"));
        reuseSliceIfExists = TextUtil.objectToBoolean(getTestConfig().getProperty("reuse_slice_if_exists"));
        disableCleanup = TextUtil.objectToBoolean(getTestConfig().getProperty("disable_slice_cleanup"));
        if (createSliceIfNotExists == null) createSliceIfNotExists = true;
        if (reuseSliceIfExists == null) reuseSliceIfExists = false;
        if (disableCleanup == null) disableCleanup = false;

        commonAMTest.selectRegularTestCredentialType(this);

        commonAMTest.setupProxyForConnectionPool(getTestConfig());
    }

    @Test(groups = {"getversion"})
    public void testGetVersionXmlRpcCorrectness() throws JFedException {
        AggregateManager3.AggregateManagerReply<AggregateManager3.VersionInfo> reply =
                am3.getVersion(getAM3Connection());

        testAM3CorrectnessXmlRpcResult(reply.getRawResult());

        //GetVersion is the only method where we have to check for something extra in the raw XMLRPC result
        versionRawResult = reply.getRawResult();
        assertNotNull(versionRawResult);

        Object ver =
                versionRawResult.get("geni_api"); //this is here for backward compatibility with v1. GetVersion returns this on all versions.
        assertNotNull(ver);
        assertTrue(ver instanceof Integer);
        int v = (Integer) ver;
        assertEquals(v, 3, "AM (backward compatibility \"geni_api\" field) is not version 3");


        assertEquals(reply.getGeniResponseCode(), GeniAMResponseCode.GENIRESPONSE_SUCCESS, "GeniResponse code is not SUCCESS (0)");

        versionInfo = reply.getValue();
        assertNotNull(versionInfo);
        assertEquals(versionInfo.getApi(), 3, "AM is not version 3");
    }

    public CommonAMTest.SliceInfo createTestSlice(String suffix) throws JFedException, IOException {
        CommonAMTest.SliceInfo slice = null;

        String fixedSliceName = getTestConfig().getProperty("fixed_slice_name");
        String fixedProjectName = getTestConfig().getProperty("fixed_project_name"); //may be null, in that case, no sub authority is used, unless mandatory
        boolean tryToUseProject = TextUtil.objectToBoolean(getTestConfig().getProperty("try_to_use_project_for_slices"))  != Boolean.FALSE; //so default is tru

        if (reuseSliceIfExists && fixedSliceName != null) {
            //check if exists: reuseSlice returns info if exists, null otherwise
            slice = commonAMTest.reuseSlice(fixedSliceName + suffix);

            if (slice == null && !createSliceIfNotExists)
                throw new RuntimeException("create_slice_if_not_exists is false, and slice does not exist.");
        }

        if (slice == null) {
            if (fixedSliceName == null)
                slice = commonAMTest.createSlice(suffix, fixedProjectName, tryToUseProject, false /*supportsFixedRspecOption*/);
            else
                slice = commonAMTest.createSlice(fixedSliceName + suffix, false, fixedProjectName, tryToUseProject, false /*supportsFixedRspecOption*/);
        }

        assertNotNull(slice.urnString, "slice" + suffix + ".urnString may not be null");
        assertTrue(slice.urnString.startsWith("urn:publicid:IDN+"));
        assertNotNull(slice.credentials, "sliceS.credential may not be null");
        assertNotEmpty(slice.credentials, "sliceS.credential may not be empty");
        assertValidUrn(slice.urnString, "slice");

        return slice;
    }


    @Test(hardDepends = {"testGetVersionXmlRpcCorrectness"},
            description = "Create the slice used in the next tests")
    public void createTestSliceP() throws JFedException, IOException {
        sliceP = createTestSlice("P");
    }

    @Test(hardDepends = {"testGetVersionXmlRpcCorrectness"},
            description = "Create the slice used in the next tests", groups = {"testRenew"})
    public void createTestSliceR() throws JFedException, IOException {
        skip("test not yet implemented");
        sliceR = createTestSlice("R");
    }

    @Test(hardDepends = {"testGetVersionXmlRpcCorrectness"},
            description = "Create the slice used in the next tests", groups = {"testPerformOperationAction"})
    public void createTestSliceOA() throws JFedException, IOException {
        skip("test not yet implemented");
        sliceOA = createTestSlice("OA");
    }

    @Test(hardDepends = {"createTestSliceP"}, groups = {"testProvision"})
    public void testAllocateP() throws JFedException, NoSuchAlgorithmException, ParseException {
        assertNotNull(sliceP);

        final String requestRspecP1 = commonAMTest.getOneNodeRequestRSpec(testedAuthority.getServerForRspecComponentManager(), sliceP.urn);

        if (requestRspecP1 == null)
            skip("testCreateSliver skipped, because no RSpec example known for type=\"" + testedAuthority.getServerForRspecComponentManager().getServerType() + "\"");

        //an RSpec that fails in Provision: 2 times same bound node
        //TODO: make non wall2 specific
        final String requestRspecP2 =
//                "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
                "<rspec type=\"request\" " +
                        "       xsi:schemaLocation=\"http://www.geni.net/resources/rspec/3 http://www.geni.net/resources/rspec/3/request.xsd\" " +
                        "       xmlns=\"http://www.geni.net/resources/rspec/3\" " +
//                "       xmlns:jFed=\"http://jfed.iminds.be/rspec/ext/jfed/1\" " +
//                "       xmlns:delay=\"http://www.protogeni.net/resources/rspec/ext/delay/1\" " +
                        "       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" +
                        "    <node client_id=\"node0\" " +
                        "          component_id=\"urn:publicid:IDN+wall2.ilabt.iminds.be+node+n091-01\" " +
                        "          component_manager_id=\"urn:publicid:IDN+wall2.ilabt.iminds.be+authority+cm\" " +
                        "          exclusive=\"true\">\n" +
                        "        <sliver_type name=\"raw-pc\"/>\n" +
                        "    </node>\n" +
                        "    <node client_id=\"node1\" " +
                        "          component_id=\"urn:publicid:IDN+wall2.ilabt.iminds.be+node+n091-01\" " +
                        "          component_manager_id=\"urn:publicid:IDN+wall2.ilabt.iminds.be+authority+cm\"" +
                        "          exclusive=\"true\">\n" +
                        "        <sliver_type name=\"raw-pc\"/>\n" +
                        "    </node>\n" +
                        "</rspec>\n";


        Date expireDate = new Date(System.currentTimeMillis() + (60 * 60 * 1000L)); //1 hour
        String endTime = RFC3339Util.dateToRFC3339String(expireDate);


        AggregateManager3.AggregateManagerReply<AggregateManager3.AllocateAndProvisionInfo> replyP2 =
                am3.allocate(getAM3Connection(), sliceP.urnString, commonAMTest.getSliceCredentialListForAM(sliceP), requestRspecP2, endTime, commonAMTest.addCredentialExtraOptions(null));
        assertEquals(replyP2.getGeniResponseCode(), GeniAMResponseCode.GENIRESPONSE_SUCCESS, "Allocate P2 did not succeed");
        AggregateManager3.AllocateAndProvisionInfo allocateAndProvisionInfoP2 = replyP2.getValue();
        String replyRequestRspecP2 = allocateAndProvisionInfoP2.getRspec();
        assertNotNull(replyRequestRspecP2, "Allocate should return an RSpec" + replyRequestRspecP2);
        List<AggregateManager3.SliverInfo> sliverInfosP2 = allocateAndProvisionInfoP2.getSliverInfo();
        assertTrue(sliverInfosP2.size() >= 1, "should be at least 1 sliver allocated");
        urnSliverP2 = new ArrayList<>();
        for (AggregateManager3.SliverInfo sliverInfoP2 : sliverInfosP2) {
            assertEquals(sliverInfoP2.getAllocationStatus(), "geni_allocated", "Allocated sliver should be in geni_allocated state");
            String sliverP2UrnStr = sliverInfoP2.getSliverUrn();
            assertNotNull(sliverP2UrnStr);
            assertValidUrn(sliverP2UrnStr, "sliver");
            urnSliverP2.add(new ResourceUrn(sliverP2UrnStr));
        }
        note("Allocated slivers P2 for slice=\"" + sliceP.urnString + "\" sliver_urns=" + urnSliverP2 + "");


        AggregateManager3.AggregateManagerReply<AggregateManager3.AllocateAndProvisionInfo> replyP1 =
                am3.allocate(getAM3Connection(), sliceP.urnString, commonAMTest.getSliceCredentialListForAM(sliceP), requestRspecP1, endTime, commonAMTest.addCredentialExtraOptions(null));
        assertEquals(replyP1.getGeniResponseCode(), GeniAMResponseCode.GENIRESPONSE_SUCCESS, "Allocate P1 did not succeed");
        AggregateManager3.AllocateAndProvisionInfo allocateAndProvisionInfoP1 = replyP1.getValue();
        String replyRequestRspecP1 = allocateAndProvisionInfoP1.getRspec();
        assertNotNull(replyRequestRspecP1, "Allocate should return an RSpec" + replyRequestRspecP1);
        List<AggregateManager3.SliverInfo> sliverInfosP1 = allocateAndProvisionInfoP1.getSliverInfo();
        assertEquals(sliverInfosP1.size(), 1, "should be exactly 1 sliver allocated");
        AggregateManager3.SliverInfo sliverInfoP1 = sliverInfosP1.get(0);
        assertEquals(sliverInfoP1.getAllocationStatus(), "geni_allocated", "Allocated sliver should be in geni_allocated state");
        String sliverP1UrnStr = sliverInfoP1.getSliverUrn();
        assertNotNull(sliverP1UrnStr);
        assertValidUrn(sliverP1UrnStr, "sliver");
        urnSliverP1 = new ResourceUrn(sliverP1UrnStr);
        note("Allocated sliver  P1 for slice=\"" + sliceP.urnString + "\" sliver_urn=\"" + urnSliverP1 + "\"");
    }

    @Test(hardDepends = {"createTestSliceR"}, softDepends = {"testProvisionP"}, groups = {"testRenew"})
    public void testAllocateR() throws JFedException, NoSuchAlgorithmException, ParseException {
        assertNotNull(sliceR);

        final String requestRspecR1 = commonAMTest.getOneNodeRequestRSpec(testedAuthority.getServerForRspecComponentManager(), sliceR.urn);
        final String requestRspecR2 = commonAMTest.getOneNodeRequestRSpec(testedAuthority.getServerForRspecComponentManager(), sliceR.urn);

        if (requestRspecR1 == null)
            skip("testCreateSliver skipped, because no RSpec example known for type=\"" + testedAuthority.getServerForRspecComponentManager().getServerType() + "\"");
        if (requestRspecR2 == null)
            skip("testCreateSliver skipped, because no RSpec example known for type=\"" + testedAuthority.getServerForRspecComponentManager().getServerType() + "\"");


        Date expireDate = new Date(System.currentTimeMillis() + (60 * 60 * 1000L)); //1 hour
        String endTime = RFC3339Util.dateToRFC3339String(expireDate);


        AggregateManager3.AggregateManagerReply<AggregateManager3.AllocateAndProvisionInfo> replyR1 =
                am3.allocate(getAM3Connection(), sliceR.urnString, commonAMTest.getSliceCredentialListForAM(sliceR), requestRspecR1, endTime, commonAMTest.addCredentialExtraOptions(null));
        assertEquals(replyR1.getGeniResponseCode(), GeniAMResponseCode.GENIRESPONSE_SUCCESS, "Allocate R1 did not succeed");
        AggregateManager3.AllocateAndProvisionInfo allocateAndProvisionInfoR1 = replyR1.getValue();
        String replyRequestRspecR1 = allocateAndProvisionInfoR1.getRspec();
        assertNotNull(replyRequestRspecR1, "Allocate should return an RSpec" + replyRequestRspecR1);
        List<AggregateManager3.SliverInfo> sliverInfosR1 = allocateAndProvisionInfoR1.getSliverInfo();
        assertEquals(sliverInfosR1.size(), 1, "should be exactly 1 sliver allocated");
        AggregateManager3.SliverInfo sliverInfoR1 = sliverInfosR1.get(0);
        assertEquals(sliverInfoR1.getAllocationStatus(), "geni_allocated", "Allocated sliver should be in geni_allocated state");
        String sliverR1UrnStr = sliverInfoR1.getSliverUrn();
        assertNotNull(sliverR1UrnStr);
        assertValidUrn(sliverR1UrnStr, "sliver");
        urnSliverR1 = new ResourceUrn(sliverR1UrnStr);
        note("Allocated sliver  R1 for slice=\"" + sliceR.urnString + "\" sliver_urn=\"" + urnSliverR1 + "\"");


        AggregateManager3.AggregateManagerReply<AggregateManager3.AllocateAndProvisionInfo> replyR2 =
                am3.allocate(getAM3Connection(), sliceR.urnString, commonAMTest.getSliceCredentialListForAM(sliceR), requestRspecR2, endTime, commonAMTest.addCredentialExtraOptions(null));
        assertEquals(replyR2.getGeniResponseCode(), GeniAMResponseCode.GENIRESPONSE_SUCCESS, "Allocate R2 did not succeed");
        AggregateManager3.AllocateAndProvisionInfo allocateAndProvisionInfoR2 = replyR2.getValue();
        String replyRequestRspecR2 = allocateAndProvisionInfoR2.getRspec();
        assertNotNull(replyRequestRspecR2, "Allocate should return an RSpec" + replyRequestRspecR2);
        List<AggregateManager3.SliverInfo> sliverInfosR2 = allocateAndProvisionInfoR2.getSliverInfo();
        assertEquals(sliverInfosR2.size(), 1, "should be exactly 1 sliver allocated");
        AggregateManager3.SliverInfo sliverInfoR2 = sliverInfosR2.get(0);
        assertEquals(sliverInfoR2.getAllocationStatus(), "geni_allocated", "Allocated sliver should be in geni_allocated state");
        String sliverR2UrnStr = sliverInfoR2.getSliverUrn();
        assertNotNull(sliverR2UrnStr);
        assertValidUrn(sliverR2UrnStr, "sliver");
        urnSliverR2 = new ResourceUrn(sliverR2UrnStr);
        note("Allocated sliver  R2 for slice=\"" + sliceR.urnString + "\" sliver_urn=\"" + urnSliverR2 + "\"");
    }


    @Test(hardDepends = {"testAllocateP"}, groups = {"testProvision"})
    public void testProvisionP() throws JFedException, NoSuchAlgorithmException, ParseException {
        assertNotNull(sliceP);
        assertNotNull(urnSliverP1);
        assertNotNull(urnSliverP2);
        assertNotEmpty(urnSliverP2);

        SSHKeyHelper dummyKeys = new SSHKeyHelper();

        List<String> sshKeys = new ArrayList<>();
        sshKeys.add(dummyKeys.getSshPublicKeyString());
        UserSpec userSpec = new UserSpec(user.getUserUrnString(), sshKeys);
        List<UserSpec> users = new ArrayList<>();
        users.add(userSpec);

        Date expireDate = new Date(System.currentTimeMillis() + (90 * 60 * 1000L)); //90 minutes in the future
        String endTime = RFC3339Util.dateToRFC3339String(expireDate);

        List<String> urns = new ArrayList<>();
        urns.add(urnSliverP1.getValue());
        for (ResourceUrn urn : urnSliverP2)
            urns.add(urn.getValue());

        AggregateManager3.AggregateManagerReply<AggregateManager3.AllocateAndProvisionInfo> replyProvision =
                am3.provision(getAM3Connection(), urns, commonAMTest.getSliceCredentialListForAM(sliceP),
                        commonAMTest.getRspecTypeName(getTestConfig()), commonAMTest.getRspecTypeVersion(getTestConfig()), null/*bestEffort*/, endTime/*endTime*/, users/*users*/, commonAMTest.addCredentialExtraOptions(null) /*extraoptions*/);

        assertNotEquals(replyProvision.getGeniResponseCode(), GeniAMResponseCode.GENIRESPONSE_SUCCESS, "Provision succeeded, but should have failed");


        AggregateManager3.AggregateManagerReply<AggregateManager3.StatusInfo> replyStatus =
                am3.status(getAM3Connection(), toStringList(sliceP.urnString),
                        commonAMTest.getSliceCredentialListForAM(sliceP), true/*best effort*/, commonAMTest.addCredentialExtraOptions(null));

        assertEquals(replyProvision.getGeniResponseCode(), GeniAMResponseCode.GENIRESPONSE_SEARCHFAILED, "Provision failed, but Status should have failed as well");


    }

    /* Test must run after tests that use sliver. Will always run, to cleanup any created sliver. */
    @Test(softDepends = {"testProvisionP", "testAllocateR", "testAllocateP"}, groups = {"testProvision", "testRenew",
                                                                                        "testPerformOperationAction"})
    public void testDeleteSliver() throws JFedException {
        if (disableCleanup) skip("No cleanup needed.");

        List<CommonAMTest.SliceInfo> slicesToDelete = new ArrayList<>();
        slicesToDelete.add(sliceR);
        slicesToDelete.add(sliceP);
        slicesToDelete.add(sliceOA);

        for (CommonAMTest.SliceInfo slice : slicesToDelete) {
            if (slice == null || slice.urnString == null)
                note("Skipped a Delete because other test created nothing to delete");
            else {
                note("Delete for slice " + slice.urnString);

                try {
                    //Test Delete Sliver by slice URN
                    AggregateManager3.AggregateManagerReply<List<AggregateManager3.SliverInfo>> reply2 =
                            am3.delete(getAM3Connection(), toStringList(slice.urnString), commonAMTest.getSliceCredentialListForAM(slice), null/*best effort*/, commonAMTest.addCredentialExtraOptions(null));

                    testAM3CorrectnessXmlRpcResult(reply2.getRawResult());

                    assertEquals(reply2.getGeniResponseCode(), GeniAMResponseCode.GENIRESPONSE_SUCCESS,
                            "DeleteSliver reply GeniResponse code is not SUCCESS (0) when given a slice \"" + slice.urnString + "\" that has a sliver.");

                    List<AggregateManager3.SliverInfo> sliverInfos = reply2.getValue();

                    for (AggregateManager3.SliverInfo sliverInfo : sliverInfos) {
                        String resSliverSUrnStr = sliverInfo.getSliverUrn();
                        assertNotNull(resSliverSUrnStr);
                        assertValidUrn(resSliverSUrnStr, "sliver");
                        assertNotNull(sliverInfo.getAllocationStatus());
                        assertEquals(sliverInfo.getAllocationStatus(), "geni_unallocated");
                    }
                } catch (Exception e) {
                    //log error but continue deleting others
                    errorNonFatal("Something went wrong while deleting: " + e.getMessage());
                }
            }
        }
    }

}
