/* * 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 gobblin.util.binpacking; import java.util.List; import org.testng.Assert; import org.testng.annotations.Test; import com.google.common.collect.Lists; import gobblin.source.workunit.Extract; import gobblin.source.workunit.MultiWorkUnit; import gobblin.source.workunit.WorkUnit; import gobblin.source.workunit.WorkUnitWeighter; public class WorstFitDecreasingBinPackingTest { public static final String WEIGHT = "weight"; WorkUnitWeighter weighter = new FieldWeighter(WEIGHT); @Test public void testBasicPacking() throws Exception { List<WorkUnit> workUnitList = Lists.newArrayList( getWorkUnitWithWeight(10), getWorkUnitWithWeight(10)); List<WorkUnit> multiWorkUnits = new WorstFitDecreasingBinPacking(20).pack(workUnitList, weighter); Assert.assertEquals(multiWorkUnits.size(), 1); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(0)).getWorkUnits().size(), 2); workUnitList = Lists.newArrayList( getWorkUnitWithWeight(10), getWorkUnitWithWeight(20)); multiWorkUnits = new WorstFitDecreasingBinPacking(20).pack(workUnitList, weighter); Assert.assertEquals(multiWorkUnits.size(), 2); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(0)).getWorkUnits().size(), 1); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(1)).getWorkUnits().size(), 1); workUnitList = Lists.newArrayList( getWorkUnitWithWeight(10), getWorkUnitWithWeight(10), getWorkUnitWithWeight(20)); multiWorkUnits = new WorstFitDecreasingBinPacking(20).pack(workUnitList, weighter); Assert.assertEquals(multiWorkUnits.size(), 2); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(0)).getWorkUnits().size(), 1); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(1)).getWorkUnits().size(), 2); } @Test public void testLargeWorkUnits() throws Exception { // Accept even large work units that don't fit in a single bucket List<WorkUnit> workUnitList = Lists.newArrayList( getWorkUnitWithWeight(10), getWorkUnitWithWeight(30)); List<WorkUnit> multiWorkUnits = new WorstFitDecreasingBinPacking(20).pack(workUnitList, weighter); Assert.assertEquals(multiWorkUnits.size(), 2); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(0)).getWorkUnits().size(), 1); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(1)).getWorkUnits().size(), 1); } @Test public void testOneLargeUnitManySmallUnits() throws Exception { // Check that a large work unit doesn't prevent small work units from being packed together // (this was an issue in a previous implementation of the algorithm) List<WorkUnit> workUnitList = Lists.newArrayList( getWorkUnitWithWeight(10), getWorkUnitWithWeight(10), getWorkUnitWithWeight(10), getWorkUnitWithWeight(10000)); List<WorkUnit> multiWorkUnits = new WorstFitDecreasingBinPacking(50).pack(workUnitList, weighter); Assert.assertEquals(multiWorkUnits.size(), 2); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(0)).getWorkUnits().size(), 3); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(1)).getWorkUnits().size(), 1); } @Test public void testMaxSizeZero() throws Exception { // If maxSize is 0, one work unit per bin List<WorkUnit> workUnitList = Lists.newArrayList( getWorkUnitWithWeight(1), getWorkUnitWithWeight(1)); List<WorkUnit> multiWorkUnits = new WorstFitDecreasingBinPacking(0).pack(workUnitList, weighter); Assert.assertEquals(multiWorkUnits.size(), 2); Assert.assertEquals(workUnitList, multiWorkUnits); } @Test public void testOverflows() throws Exception { // Test overflows List<WorkUnit> workUnitList = Lists.newArrayList( getWorkUnitWithWeight(Long.MAX_VALUE), getWorkUnitWithWeight(Long.MAX_VALUE), getWorkUnitWithWeight(10)); List<WorkUnit> multiWorkUnits = new WorstFitDecreasingBinPacking(100).pack(workUnitList, weighter); Assert.assertEquals(multiWorkUnits.size(), 3); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(0)).getWorkUnits().size(), 1); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(1)).getWorkUnits().size(), 1); Assert.assertEquals(((MultiWorkUnit) multiWorkUnits.get(2)).getWorkUnits().size(), 1); } public WorkUnit getWorkUnitWithWeight(long weight) { WorkUnit workUnit = new WorkUnit(new Extract(Extract.TableType.APPEND_ONLY, "", "")); workUnit.setProp(WEIGHT, Long.toString(weight)); return workUnit; } }