/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jackrabbit.oak.plugins.document;

import java.util.Random;

import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.plugins.document.memory.MemoryDocumentStore;
import org.apache.jackrabbit.oak.plugins.document.util.Utils;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.stats.Clock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.jackrabbit.oak.plugins.document.TestUtils.merge;
import static org.apache.jackrabbit.oak.plugins.document.util.Utils.getAllDocuments;
import static org.junit.Assert.assertTrue;

public class RandomDocumentNodeStoreSweepTest {

    private static final Logger LOG = LoggerFactory.getLogger(RandomDocumentNodeStoreSweepTest.class);

    private Random random = new Random(42);

    private int numNodes = 0;

    private int numProperties = 0;

    private Clock clock;

    private FailingDocumentStore store;

    private DocumentNodeStore ns;

    @Before
    public void before() throws Exception {
        clock = new Clock.Virtual();
        clock.waitUntil(System.currentTimeMillis());
        Revision.setClock(clock);
        ClusterNodeInfo.setClock(clock);
        store = new FailingDocumentStore(new MemoryDocumentStore());
        ns = createDocumentNodeStore();
    }

    @After
    public void after() {
        ns.dispose();
        Revision.resetClockToDefault();
        ClusterNodeInfo.resetClockToDefault();
    }

    @Test
    public void randomFailures() throws Exception {
        Random r = new Random(23);
        for (int i = 0; i < 1000; i++) {
            int n = r.nextInt(10);
            switch (n) {
                case 0:
                case 1:
                case 2:
                    addNode();
                    break;
                case 3:
                case 4:
                case 5:
                case 6:
                    addProperty();
                    break;
                case 7:
                    removeProperty();
                    break;
                case 8:
                    ns.runBackgroundOperations();
                    break;
                case 9:
                    restartAndCheckStore();
                    break;
            }
        }
    }

    private void restartAndCheckStore() throws InterruptedException {
        LOG.info("crashing DocumentNodeStore");
        // let it crash
        store.fail().after(0).eternally();
        try {
            ns.dispose();
        } catch (DocumentStoreException e) {
            // expected
        }
        store.fail().never();
        // wait until lease expires
        clock.waitUntil(clock.getTime() + ClusterNodeInfo.DEFAULT_LEASE_DURATION_MILLIS);
        LOG.info("restarting DocumentNodeStore");
        ns = createDocumentNodeStore();
        LOG.info("checking for uncommitted changes");
        assertCleanStore();
    }

    private void removeProperty() throws CommitFailedException {
        maybeFail(new Operation() {
            @Override
            public void call() throws CommitFailedException {
                if (numNodes == 0) {
                    return;
                }
                NodeBuilder builder = ns.getRoot().builder();
                // try ten times to find a node with a property
                for (int i = 0; i < 10; i++) {
                    String name = "node-" + random.nextInt(numNodes);
                    for (PropertyState p : builder.child(name).getProperties()) {
                        builder.child(name).removeProperty(p.getName());
                        merge(ns, builder);
                        return;
                    }
                }
            }
        }, "removing property");
    }

    private void addProperty() throws CommitFailedException {
        maybeFail(new Operation() {
            @Override
            public void call() throws CommitFailedException {
                if (numNodes == 0) {
                    return;
                }
                String name = "node-" + random.nextInt(numNodes);
                NodeBuilder builder = ns.getRoot().builder();
                builder.child(name).setProperty("property-" + numProperties, "value");
                merge(ns, builder);
                numProperties++;
            }
        }, "adding property");
    }

    private void addNode() throws CommitFailedException {
        maybeFail(new Operation() {
            @Override
            public void call() throws CommitFailedException {
                NodeBuilder builder = ns.getRoot().builder();
                builder.child("node-" + numNodes);
                merge(ns, builder);
                numNodes++;
            }
        }, "adding node");
    }



    private void maybeFail(Operation op, String message)
            throws CommitFailedException {
        if (failOperation()) {
            guardedFail(op, message);
        } else {
            op.call();
            LOG.info(message);
        }
    }

    private void guardedFail(Operation op, String message) {
        store.fail().after(1).eternally();
        try {
            op.call();
            LOG.info(message);
        } catch (Exception e) {
            LOG.info(message + " failed");
        } finally {
            store.fail().never();
        }
    }

    private boolean failOperation() {
        // fail 10% of the operations
        return random.nextInt(10) == 0;
    }

    private DocumentNodeStore createDocumentNodeStore() {
        DocumentNodeStore ns = new DocumentMK.Builder().setDocumentStore(store)
                .clock(clock).setClusterId(1).setAsyncDelay(0)
                .setLeaseCheckMode(LeaseCheckMode.DISABLED).getNodeStore();
        // do not retry commits
        ns.setMaxBackOffMillis(0);
        return ns;
    }

    private void assertCleanStore() {
        for (NodeDocument doc : getAllDocuments(store)) {
            for (Revision c : doc.getAllChanges()) {
                String commitValue = ns.getCommitValue(c, doc);
                assertTrue("Revision " + c + " on " + doc.getId() + " is not committed: " + commitValue,
                        Utils.isCommitted(commitValue));
            }
        }
    }

    interface Operation {
        void call() throws CommitFailedException;
    }
}
