/*
 * 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.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 NetworkParameters UNITTEST;

    public VersionTallyTest() {
    }

    @BeforeClass
    public static void setUpClass() {
        Utils.resetMocking();
        UNITTEST = UnitTestParams.get();
    }

    @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(UNITTEST);
        for (int i = 0; i < UNITTEST.getMajorityWindow(); i++) {
            assertNull(instance.getCountAtOrAbove(1));
            instance.add(1);
        }
        assertEquals(UNITTEST.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(UNITTEST);
        assertEquals(UNITTEST.getMajorityWindow(), instance.size());
    }

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

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

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

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

    @Test
    public void testInitialize() throws BlockStoreException {
        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());
    }
}

@@ -767,24 +767,67 @@
 core.Utils;%0A
+import org.bitcoinj.params.TestNet3Params;%0A
 import org.b
@@ -1248,16 +1248,22 @@
  static 
+final 
 NetworkP
@@ -1272,24 +1272,46 @@
 ameters 
-UNIT
 TEST
+NET = TestNet3Params.get()
 ;%0A%0A    p
@@ -1433,49 +1433,8 @@
 ();%0A
-        UNITTEST = UnitTestParams.get();%0A
     
@@ -1709,39 +1709,38 @@
 ew VersionTally(
-UNIT
 TES
+TNE
 T);%0A        for 
@@ -1747,39 +1747,38 @@
 (int i = 0; i %3C 
-UNIT
 TES
+TNE
 T.getMajorityWin
@@ -1898,39 +1898,38 @@
    assertEquals(
-UNIT
 TES
+TNE
 T.getMajorityWin
@@ -2162,39 +2162,38 @@
 ew VersionTally(
-UNIT
 TES
+TNE
 T);%0A        asse
@@ -2193,39 +2193,38 @@
    assertEquals(
-UNIT
 TES
+TNE
 T.getMajorityWin
@@ -2431,31 +2431,30 @@
 ersionTally(
-UNIT
 TES
+TNE
 T);%0A%0A       
@@ -2500,39 +2500,38 @@
 (int i = 0; i %3C 
-UNIT
 TES
+TNE
 T.getMajorityWin
@@ -2651,39 +2651,38 @@
    assertEquals(
-UNIT
 TES
+TNE
 T.getMajorityWin
@@ -2817,23 +2817,22 @@
  0; i %3C 
-UNIT
 TES
+TNE
 T.getMaj
@@ -3031,39 +3031,38 @@
    assertEquals(
-UNIT
 TES
+TNE
 T.getMajorityWin
@@ -3202,39 +3202,38 @@
    assertEquals(
-UNIT
 TES
+TNE
 T.getMajorityWin
@@ -3365,16 +3365,107 @@
 ption %7B%0A
+        final NetworkParameters UNITTEST = UnitTestParams.get(); // easy difficulty target%0A
         

use TestNet3Params where possible, rather than UnitTestParams