Package com.rackspacecloud.blueflood.rollup

Source Code of com.rackspacecloud.blueflood.rollup.SlotTest

/*
* Copyright 2013 Rackspace
*
*    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 com.rackspacecloud.blueflood.rollup;

import com.rackspacecloud.blueflood.exceptions.GranularityException;
import com.rackspacecloud.blueflood.types.Range;
import org.junit.Assert;
import org.junit.Test;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class SlotTest {
    private static final int shard = 0;
   
    @Test
    public void testSlotIterator() {
        long baseMillis = 1331650343000L;
        int expectedSlot = 3634;
        String expectedLocatorKey = Granularity.FULL.formatLocatorKey(expectedSlot, shard);
       
       
        Set<String> expected = new HashSet<String>();
        expected.add(expectedLocatorKey);
        expected.add(Granularity.FULL.formatLocatorKey(expectedSlot + 1, shard));
       
        Set<String> actual = new HashSet<String>();
        for (String i : Granularity.FULL.locatorKeys(shard, baseMillis, baseMillis + 300000))
            actual.add(i);
        Assert.assertEquals(expected, actual);
       
        actual.clear();
        expected.clear();
       
        // test wrapping slots.
        expected.add(Granularity.FULL.formatLocatorKey(Granularity.FULL.numSlots() - 2, shard));
        expected.add(Granularity.FULL.formatLocatorKey(Granularity.FULL.numSlots() - 1, shard));
        expected.add(Granularity.FULL.formatLocatorKey(0, shard));
        expected.add(Granularity.FULL.formatLocatorKey(1, shard));
        int scale = Granularity.FULL.numSlots() - expectedSlot - 2; // puts me 2 slots before the end.
        for (String locatorKey : Granularity.FULL.locatorKeys(shard, baseMillis + (scale * 300000), baseMillis + ((scale + 3) * 300000)))
            actual.add(locatorKey);
        Assert.assertEquals(expected, actual);
    }
   
    @Test
    public void testRangeIteratorFullAnd5m() throws Exception {
        Set<Range> expectedRanges = new HashSet<Range>();
        expectedRanges.add(new Range(0, 299999));
        expectedRanges.add(new Range(300000, 599999));
        expectedRanges.add(new Range(600000, 899999));
        expectedRanges.add(new Range(900000, 1199999));
       
        // FULL and 5m have the same rollup semantics.
        for (Granularity g : new Granularity[] { Granularity.FULL, Granularity.MIN_5}) {
            Set<Range> actualRanges = new HashSet<Range>();
            for (Range time : Range.getRangesToRollup(g, 200000, 1000000)) {
                actualRanges.add(time);
                verifySingleSlot(time, g);
            }
            Assert.assertEquals(expectedRanges, actualRanges);
        }
    }
   
    @Test
    public void testRangeIterator20m() throws Exception {
        Set<Range> expectedRanges = makeRanges(Granularity.MIN_20, 3600000, 33);
        Set<Range> actualRanges = new HashSet<Range>();
        int baseMillis = 6500000;
        int hrs = 10;
        int endMillis = baseMillis + 3600000 * hrs;
        for (Range time : Range.getRangesToRollup(Granularity.MIN_20, baseMillis, endMillis)) {
            actualRanges.add(time);
            verifySingleSlot(time, Granularity.MIN_20);
        }
        Assert.assertEquals(expectedRanges, actualRanges);
    }

    @Test
    public void testRangeMapper60m() throws Exception {
        int baseMillis = 6500000;
        int hrs = 10;
        int endMillis = baseMillis + 3600000 * hrs;
        //Map of every 60m(coarser gran) in this time range, mapped to iterable of 20m sub-ranges that get rolled up
        Map<Range, Iterable<Range>> retMap = Range.mapFinerRanges(Granularity.MIN_60, new Range(baseMillis, endMillis));
        Assert.assertEquals(retMap.entrySet().size(), 11);
        for(Map.Entry<Range,Iterable<Range>> entry : retMap.entrySet()) {
            Range coarserSubRange = entry.getKey();
            int iterValCount = 0;
            Iterable<Range> subranges = entry.getValue();
            for (Range subrange : subranges) {
                if(iterValCount == 0) {
                    //Start point of coarser range is equal to start point of 1st 20m sub-range
                    Assert.assertEquals(coarserSubRange.getStart(), subrange.getStart());
                }
                iterValCount++;
                if(iterValCount == 3) {
                    Assert.assertEquals(coarserSubRange.getStop() - 1, subrange.getStop());
                }
            }
            //Every 60m range gets divided into 3 20m sub-ranges
            Assert.assertEquals(iterValCount, 3);
        }
    }
   
    @Test
    public void testRangeIterator60m() throws Exception {
        Set<Range> expectedRanges = makeRanges(Granularity.MIN_60, 1334577600000L, 72);
        Set<Range> actualRanges = new HashSet<Range>();
        long baseMillis = 1334582854000L; // nearly Mon Apr 16 06:26:52 PDT 2012
        int hrs = 70;
        long endMillis = baseMillis + 3600000 * hrs;
        for (Range time : Range.getRangesToRollup(Granularity.MIN_60, baseMillis, endMillis)) {
            actualRanges.add(time);
            verifySingleSlot(time, Granularity.MIN_60);
        }
        Assert.assertEquals(expectedRanges, actualRanges);
    }
   
    @Test
    public void testRangeIterator240m() throws Exception {
        Set<Range> expectedRanges = makeRanges(Granularity.MIN_240, 1334534400000L, 66);
        Set<Range> actualRanges = new HashSet<Range>();
        long baseMillis = 1334582854000L; // nearly Mon Apr 16 06:26:52 PDT 2012
        int hrs = 240; // 10 days.
        long endMillis = baseMillis + 3500000 * hrs; // todo: should be 3600000?
        for (Range time : Range.getRangesToRollup(Granularity.MIN_240, baseMillis, endMillis)) {
            actualRanges.add(time);
            verifySingleSlot(time, Granularity.MIN_240);   
        }
        Assert.assertEquals(expectedRanges, actualRanges);
    }
   
    // there is no testRangeIterator1440m because range iteration isn't defined for that granularity because there
    // is no granularity that is more coarse.
   
    // ensure that every point of time within a given range is in the same slot as the beginning of the range.
    private void verifySingleSlot(Range r, Granularity g) {
        int init = g.slot(r.start);
        for (long time = r.start; time <= r.stop; time += 1000)
            Assert.assertEquals(init, g.slot(time));
    }
   
    // create a collection of consecutive ranges.
    private static Set<Range> makeRanges(Granularity g, long startMillis, int count) {
        Set<Range> set = new HashSet<Range>();
        long millis = startMillis;
        for (int i = 0; i < count; i++) {
            long end = millis + g.milliseconds();
            set.add(new Range(millis, end - 1));
            millis = end;
        }
        return set;
    }
   
    @Test
    public void testSlotCalculationsRawAnd5m() {
        final long now = 1331650343000L;
        final long slot = 3634;
        Assert.assertEquals(slot, Granularity.millisToSlot(now));
       
        // 5 mins now should be in the next slot.
        Assert.assertEquals(slot + 1, Granularity.millisToSlot(now + Granularity.MILLISECONDS_IN_SLOT));
        Assert.assertEquals(slot + 1, Granularity.FULL.slot(now + Granularity.MILLISECONDS_IN_SLOT));
        Assert.assertEquals(slot + 1, Granularity.MIN_5.slot(now + Granularity.MILLISECONDS_IN_SLOT));
       
        // should repeat after however many seconds are in NUMBER_OF_SLOTS * MILLISECONDS_PER_SLOT
        Assert.assertEquals(slot, Granularity.millisToSlot(now + (Granularity.FULL.numSlots() * Granularity.MILLISECONDS_IN_SLOT)));
        Assert.assertEquals(slot, Granularity.FULL.slot(now + (Granularity.FULL.numSlots() * Granularity.MILLISECONDS_IN_SLOT)));
        Assert.assertEquals(slot, Granularity.MIN_5.slot(now + (Granularity.FULL.numSlots() * Granularity.MILLISECONDS_IN_SLOT)));
       
        // test the very end of the cycle.
        long endOfCycle = now + ((Granularity.FULL.numSlots() - slot - 1) * Granularity.MILLISECONDS_IN_SLOT); // basically the number of secs to get to slot == 4095
        Assert.assertEquals(Granularity.FULL.numSlots() - 1, Granularity.millisToSlot(endOfCycle));
        Assert.assertEquals(Granularity.FULL.numSlots() - 1, Granularity.FULL.slot(endOfCycle));
        Assert.assertEquals(Granularity.MIN_5.numSlots() - 1, Granularity.MIN_5.slot(endOfCycle));
       
        // adding 300s (one slot) should wrap back around to zero.
        Assert.assertEquals(0, Granularity.millisToSlot(endOfCycle + Granularity.MILLISECONDS_IN_SLOT));
        Assert.assertEquals(0, Granularity.FULL.slot(endOfCycle + Granularity.MILLISECONDS_IN_SLOT));
        Assert.assertEquals(0, Granularity.MIN_5.slot(endOfCycle + Granularity.MILLISECONDS_IN_SLOT));
    }

    @Test
    public void testSlotRelationships() {
        final long now = 1331650343000L;
        final long slot = 3634;
        Assert.assertEquals(slot, Granularity.FULL.slot(now));
        Assert.assertEquals(slot, Granularity.MIN_5.slot(now));
    
        Assert.assertEquals(Granularity.FULL.numSlots(), Granularity.MIN_5.numSlots());
        Assert.assertEquals(Granularity.FULL.numSlots() / 4, Granularity.MIN_20.numSlots());
        Assert.assertEquals(Granularity.FULL.numSlots() / 12, Granularity.MIN_60.numSlots());
        Assert.assertEquals(Granularity.FULL.numSlots() / 48, Granularity.MIN_240.numSlots());
        Assert.assertEquals(Granularity.FULL.numSlots() / 288, Granularity.MIN_1440.numSlots());
       
        // make sure there are no remainders for the minute ratios
        Assert.assertTrue(Granularity.FULL.numSlots() % 4 == 0);
        Assert.assertTrue(Granularity.FULL.numSlots() % 12 == 0);
        Assert.assertTrue(Granularity.FULL.numSlots() % 48 == 0);
        Assert.assertTrue(Granularity.FULL.numSlots() % 288 == 0);
    }

    @Test
    public void testStaticSameAsFull() {
        final long baseMillis = 1333635148000L; // some point during 5 April 2012.
        final long endMillis = baseMillis + (1000 * 60 * 60 * 48); // +48hrs
        Assert.assertEquals(Granularity.millisToSlot(baseMillis), Granularity.FULL.slot(baseMillis));
        Assert.assertEquals(Granularity.millisToSlot(endMillis), Granularity.FULL.slot(endMillis));
       
    }
   
    @Test
    // make sure the same kind of tests still pass at coarser granularities.
    public void testCoarseSlotCalculations() {
        final long now = 1334582854000L;
        Granularity[] granularities = new Granularity[] {Granularity.MIN_20, Granularity.MIN_60, Granularity.MIN_240, Granularity.MIN_1440};
        int[] initialSlots = new int[] {328, 109, 27, 4};
       
        for (int i = 0; i < initialSlots.length; i++) {
            final long slot = initialSlots[i];
            final Granularity gran = granularities[i];
           
            Assert.assertEquals(slot, gran.slot(now));
           
            // next slot should increment by 1.
            Assert.assertEquals(slot + 1, gran.slot(now + gran.milliseconds()));
           
            // should repeat.
            Assert.assertEquals(slot, gran.slot(now + gran.milliseconds() * gran.numSlots()));
           
            // very end of cycle.
            long endOfCycle = now + (gran.numSlots() - slot - 1) * gran.milliseconds();
            Assert.assertEquals(gran.numSlots() - 1, gran.slot(endOfCycle));
           
            // adding seconds() should wrap back to zero.
            Assert.assertEquals(0, gran.slot(endOfCycle + gran.milliseconds()));
        }
    }

    @Test(expected=GranularityException.class)
    public void testSlotFromFinerSlotThrowsAtFull() throws Throwable {
        try {
            Granularity.FULL.slotFromFinerSlot(123);
        } catch (RuntimeException e) {
            throw e.getCause();
        }
    }

    @Test
    public void testSlotFromFinerSlot() {
        // i.e, slot 144 for a 5m is == slot 36 of 20m ( 144 / (20/5)), slot 12 at 60m, slot 3 at 240m, etc
        try {
            Assert.assertEquals(256, Granularity.MIN_5.slotFromFinerSlot(256));

            Assert.assertEquals(35, Granularity.MIN_20.slotFromFinerSlot(143));
            Assert.assertEquals(36, Granularity.MIN_20.slotFromFinerSlot(144));
            Assert.assertEquals(36, Granularity.MIN_20.slotFromFinerSlot(145));
            Assert.assertEquals(36, Granularity.MIN_20.slotFromFinerSlot(146));
            Assert.assertEquals(36, Granularity.MIN_20.slotFromFinerSlot(147));
            Assert.assertEquals(37, Granularity.MIN_20.slotFromFinerSlot(148));

            Assert.assertEquals(12, Granularity.MIN_60.slotFromFinerSlot(36));
            Assert.assertEquals(3, Granularity.MIN_240.slotFromFinerSlot(12));
            Assert.assertEquals(2, Granularity.MIN_1440.slotFromFinerSlot(13));
        } catch (GranularityException e) {
            Assert.assertNull("GranularityException seen on non-full-res Granularity", e);
        }
    }

   
    @Test
    public void testRangeDerivation() {
        for (Granularity gran : Granularity.granularities()) {
            long now = 1334582854000L;
            int nowSlot = gran.slot(now);
            now = gran.snapMillis(now);
            Range nowRange = new Range(now, now + gran.milliseconds() - 1);
            Assert.assertEquals(nowRange, gran.deriveRange(nowSlot, now));
           
            Range prevRange = gran.deriveRange(nowSlot - 1, now);
            Assert.assertEquals(gran.milliseconds(), nowRange.start - prevRange.start);
           
            // incrementing nowSlot forces us to test slot wrapping.
            Range wayBeforeRange = gran.deriveRange(nowSlot + 1, now);
            Assert.assertEquals(gran.numSlots() - 1, (nowRange.start - wayBeforeRange.start) / gran.milliseconds());
        }
    }
  
    @Test
    public void testSlotChildren() {
        // the relationship between slots plays out here.
       
        // full res slots have no children.
        int expect = 0;
        Assert.assertEquals(expect, Granularity.FULL.getChildrenKeys(4, shard).size());
       
        // min5 slots contain only their full res counterpart.
        expect = expect * 1 + 1;
        Assert.assertEquals(expect, Granularity.MIN_5.getChildrenKeys(4, shard).size());
       
        // min20 slots contain their 4 min5 children and full res grandchildren.
        expect = expect * 4 + 4;
        Assert.assertEquals(expect, Granularity.MIN_20.getChildrenKeys(4, shard).size());
       
        // and so on. the relationship between min60 and min20 is a factor of 3.
        expect = expect * 3 + 3;
        Assert.assertEquals(expect, Granularity.MIN_60.getChildrenKeys(4, shard).size());
       
        // min240 and min60 is a factor of 4.
        expect = expect *4 + 4;
        Assert.assertEquals(expect, Granularity.MIN_240.getChildrenKeys(4, shard).size());
       
        // min1440 and min240 is a factor of 6.
        expect = expect * 6 + 6;
        Assert.assertEquals(expect, Granularity.MIN_1440.getChildrenKeys(4, shard).size());
    }
}
TOP

Related Classes of com.rackspacecloud.blueflood.rollup.SlotTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.