/*
 * Copyright 2015 Ross Nicoll.
 *
 * Licensed 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.bitcoinj.utils;

import org.bitcoinj.core.BlockChain;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.core.StoredBlock;
import org.bitcoinj.core.Utils;
import org.bitcoinj.params.TestNet3Params;
import org.bitcoinj.params.UnitTestParams;
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.BlockStoreException;
import org.bitcoinj.store.MemoryBlockStore;
import org.bitcoinj.testing.FakeTxBuilder;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

public class VersionTallyTest {
    private static final NetworkParameters TESTNET = TestNet3Params.get();

    public VersionTallyTest() {
    }

    @BeforeClass
    public static void setUpClass() {
        Utils.resetMocking();
    }

    @Before
    public void setUp() {
        BriefLogFormatter.initVerbose();
    }

    /**
     * Verify that the version tally returns null until it collects enough data.
     */
    @Test
    public void testNullWhileEmpty() {
        VersionTally instance = new VersionTally(TESTNET);
        for (int i = 0; i < TESTNET.getMajorityWindow(); i++) {
            assertNull(instance.getCountAtOrAbove(1));
            instance.add(1);
        }
        assertEquals(TESTNET.getMajorityWindow(), instance.getCountAtOrAbove(1).intValue());
    }

    /**
     * Verify that the size of the version tally matches the network parameters.
     */
    @Test
    public void testSize() {
        VersionTally instance = new VersionTally(TESTNET);
        assertEquals(TESTNET.getMajorityWindow(), instance.size());
    }

    /**
     * Verify that version count and substitution works correctly.
     */
    @Test
    public void testVersionCounts() {
        VersionTally instance = new VersionTally(TESTNET);

        // Fill the tally with 1s
        for (int i = 0; i < TESTNET.getMajorityWindow(); i++) {
            assertNull(instance.getCountAtOrAbove(1));
            instance.add(1);
        }
        assertEquals(TESTNET.getMajorityWindow(), instance.getCountAtOrAbove(1).intValue());

        // Check the count updates as we replace with 2s
        for (int i = 0; i < TESTNET.getMajorityWindow(); i++) {
            assertEquals(i, instance.getCountAtOrAbove(2).intValue());
            instance.add(2);
        }
 
        // Inject a rogue 1
        instance.add(1);
        assertEquals(TESTNET.getMajorityWindow() - 1, instance.getCountAtOrAbove(2).intValue());

        // Check we accept high values as well
        instance.add(10);
        assertEquals(TESTNET.getMajorityWindow() - 1, instance.getCountAtOrAbove(2).intValue());
    }

    @Test
    public void testInitialize() throws BlockStoreException {
        final NetworkParameters UNITTEST = UnitTestParams.get(); // easy difficulty target
        final BlockStore blockStore = new MemoryBlockStore(UNITTEST);
        final BlockChain chain = new BlockChain(UNITTEST, blockStore);

        // Build a historical chain of version 2 blocks
        long timeSeconds = 1231006505;
        StoredBlock chainHead = null;
        for (int height = 0; height < UNITTEST.getMajorityWindow(); height++) {
            chainHead = FakeTxBuilder.createFakeBlock(blockStore, 2, timeSeconds, height).storedBlock;
            assertEquals(2, chainHead.getHeader().getVersion());
            timeSeconds += 60;
        }

        VersionTally instance = new VersionTally(UNITTEST);
        instance.initialize(blockStore, chainHead);
        assertEquals(UNITTEST.getMajorityWindow(), instance.getCountAtOrAbove(2).intValue());
    }
}

@@ -657,16 +657,50 @@
 kChain;%0A
+import org.bitcoinj.core.Context;%0A
 import o
@@ -798,21 +798,27 @@
 nj.core.
-Utils
+Transaction
 ;%0Aimport
@@ -835,28 +835,17 @@
 inj.
-params.TestNet3Param
+core.Util
 s;%0Ai
@@ -870,24 +870,24 @@
 .params.
-Unit
 Test
+Net3
 Params;%0A
@@ -3406,90 +3406,85 @@
     
-final NetworkParameters UNITTEST = UnitTestParams.get(); // easy difficulty target
+Context.propagate(new Context(100, Transaction.DEFAULT_TX_FEE, false, true));
 %0A   
@@ -3539,23 +3539,22 @@
 ckStore(
-UNIT
 TES
+TNE
 T);%0A    
@@ -3597,23 +3597,22 @@
 ckChain(
-UNIT
 TES
+TNE
 T, block
@@ -3791,23 +3791,22 @@
 eight %3C 
-UNIT
 TES
+TNE
 T.getMaj
@@ -4091,23 +4091,22 @@
 onTally(
-UNIT
 TES
+TNE
 T);%0A    
@@ -4178,15 +4178,14 @@
 als(
-UNIT
 TES
+TNE
 T.ge

use TestNet3Params, rather than UnitTestParams