org.apache.hadoop.fs.slive.TestSlive.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.fs.slive.TestSlive.java

Source

/**
 * 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.hadoop.fs.slive;

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

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.slive.ArgumentParser.ParsedOutput;
import org.apache.hadoop.fs.slive.Constants.OperationType;
import org.apache.hadoop.fs.slive.DataVerifier.VerifyOutput;
import org.apache.hadoop.fs.slive.DataWriter.GenerateOutput;
import org.apache.hadoop.util.ToolRunner;
import org.junit.Before;
import org.junit.Test;

/**
 * Junit 4 test for slive
 */
public class TestSlive {

    private static final Log LOG = LogFactory.getLog(TestSlive.class);

    private static final Random rnd = new Random(1L);

    private static final String TEST_DATA_PROP = "test.build.data";

    private static Configuration getBaseConfig() {
        Configuration conf = new Configuration();
        return conf;
    }

    /** gets the test write location according to the coding guidelines */
    private static File getWriteLoc() {
        String writeLoc = System.getProperty(TEST_DATA_PROP, "build/test/data/");
        return new File(writeLoc, "slive");
    }

    /** gets where the MR job places its data + output + results */
    private static File getFlowLocation() {
        return new File(getWriteLoc(), "flow");
    }

    /** gets the test directory which is created by the mkdir op */
    private static File getTestDir() {
        return new File(getWriteLoc(), "slivedir");
    }

    /**
     * gets the test file location
     * which is used for reading, appending and created
     */
    private static File getTestFile() {
        return new File(getWriteLoc(), "slivefile");
    }

    /**
     * gets the rename file which is used in combination
     * with the test file to do a rename operation
     */
    private static File getTestRenameFile() {
        return new File(getWriteLoc(), "slivefile1");
    }

    /** gets the MR result file name */
    private static File getResultFile() {
        return new File(getWriteLoc(), "sliveresfile");
    }

    private static File getImaginaryFile() {
        return new File(getWriteLoc(), "slivenofile");
    }

    /** gets the test program arguments used for merging and main MR running */
    private String[] getTestArgs(boolean sleep) {
        List<String> args = new LinkedList<String>();
        // setup the options
        {
            args.add("-" + ConfigOption.WRITE_SIZE.getOpt());
            args.add("1M,2M");
            args.add("-" + ConfigOption.OPS.getOpt());
            args.add(Constants.OperationType.values().length + "");
            args.add("-" + ConfigOption.MAPS.getOpt());
            args.add("2");
            args.add("-" + ConfigOption.REDUCES.getOpt());
            args.add("2");
            args.add("-" + ConfigOption.APPEND_SIZE.getOpt());
            args.add("1M,2M");
            args.add("-" + ConfigOption.BLOCK_SIZE.getOpt());
            args.add("1M,2M");
            args.add("-" + ConfigOption.REPLICATION_AM.getOpt());
            args.add("1,1");
            if (sleep) {
                args.add("-" + ConfigOption.SLEEP_TIME.getOpt());
                args.add("10,10");
            }
            args.add("-" + ConfigOption.RESULT_FILE.getOpt());
            args.add(getResultFile().toString());
            args.add("-" + ConfigOption.BASE_DIR.getOpt());
            args.add(getFlowLocation().toString());
            args.add("-" + ConfigOption.DURATION.getOpt());
            args.add("10");
            args.add("-" + ConfigOption.DIR_SIZE.getOpt());
            args.add("10");
            args.add("-" + ConfigOption.FILES.getOpt());
            args.add("10");
        }
        return args.toArray(new String[args.size()]);
    }

    @Test
    public void testFinder() throws Exception {
        ConfigExtractor extractor = getTestConfig(false);
        PathFinder fr = new PathFinder(extractor, rnd);
        // should only be able to select 10 files
        // attempt for a given amount of iterations
        int maxIterations = 10000;
        Set<Path> files = new HashSet<Path>();
        for (int i = 0; i < maxIterations; i++) {
            files.add(fr.getFile());
        }
        assertTrue(files.size() == 10);
        Set<Path> dirs = new HashSet<Path>();
        for (int i = 0; i < maxIterations; i++) {
            dirs.add(fr.getDirectory());
        }
        assertTrue(dirs.size() == 10);
    }

    @Test
    public void testSelection() throws Exception {
        ConfigExtractor extractor = getTestConfig(false);
        WeightSelector selector = new WeightSelector(extractor, rnd);
        // should be 1 of each type - uniform
        int expected = OperationType.values().length;
        Operation op = null;
        Set<String> types = new HashSet<String>();
        FileSystem fs = FileSystem.get(extractor.getConfig());
        while (true) {
            op = selector.select(1, 1);
            if (op == null) {
                break;
            }
            // doesn't matter if they work or not
            op.run(fs);
            types.add(op.getType());
        }
        assertEquals(types.size(), expected);
    }

    // gets the config merged with the arguments
    private ConfigExtractor getTestConfig(boolean sleep) throws Exception {
        ArgumentParser parser = new ArgumentParser(getTestArgs(sleep));
        ParsedOutput out = parser.parse();
        assertTrue(!out.shouldOutputHelp());
        ConfigMerger merge = new ConfigMerger();
        Configuration cfg = merge.getMerged(out, getBaseConfig());
        ConfigExtractor extractor = new ConfigExtractor(cfg);
        return extractor;
    }

    @Before
    public void ensureDeleted() throws Exception {
        rDelete(getTestFile());
        rDelete(getTestDir());
        rDelete(getTestRenameFile());
        rDelete(getResultFile());
        rDelete(getFlowLocation());
        rDelete(getImaginaryFile());
    }

    /** cleans up a file or directory recursively if need be */
    private void rDelete(File place) throws Exception {
        if (place.isFile()) {
            LOG.info("Deleting file " + place);
            assertTrue(place.delete());
        } else if (place.isDirectory()) {
            deleteDir(place);
        }
    }

    /** deletes a dir and its contents */
    private void deleteDir(File dir) throws Exception {
        String fns[] = dir.list();
        // delete contents first
        for (String afn : fns) {
            File fn = new File(dir, afn);
            rDelete(fn);
        }
        LOG.info("Deleting directory " + dir);
        // now delete the dir
        assertTrue(dir.delete());
    }

    @Test
    public void testArguments() throws Exception {
        ConfigExtractor extractor = getTestConfig(true);
        assertEquals(extractor.getOpCount().intValue(), Constants.OperationType.values().length);
        assertEquals(extractor.getMapAmount().intValue(), 2);
        assertEquals(extractor.getReducerAmount().intValue(), 2);
        Range<Long> apRange = extractor.getAppendSize();
        assertEquals(apRange.getLower().intValue(), Constants.MEGABYTES * 1);
        assertEquals(apRange.getUpper().intValue(), Constants.MEGABYTES * 2);
        Range<Long> wRange = extractor.getWriteSize();
        assertEquals(wRange.getLower().intValue(), Constants.MEGABYTES * 1);
        assertEquals(wRange.getUpper().intValue(), Constants.MEGABYTES * 2);
        Range<Long> bRange = extractor.getBlockSize();
        assertEquals(bRange.getLower().intValue(), Constants.MEGABYTES * 1);
        assertEquals(bRange.getUpper().intValue(), Constants.MEGABYTES * 2);
        String resfile = extractor.getResultFile();
        assertEquals(resfile, getResultFile().toString());
        int durationMs = extractor.getDurationMilliseconds();
        assertEquals(durationMs, 10 * 1000);
    }

    @Test
    public void testDataWriting() throws Exception {
        long byteAm = 100;
        File fn = getTestFile();
        DataWriter writer = new DataWriter(rnd);
        FileOutputStream fs = new FileOutputStream(fn);
        GenerateOutput ostat = writer.writeSegment(byteAm, fs);
        LOG.info(ostat);
        fs.close();
        assertTrue(ostat.getBytesWritten() == byteAm);
        DataVerifier vf = new DataVerifier();
        FileInputStream fin = new FileInputStream(fn);
        VerifyOutput vfout = vf.verifyFile(byteAm, new DataInputStream(fin));
        LOG.info(vfout);
        fin.close();
        assertEquals(vfout.getBytesRead(), byteAm);
        assertTrue(vfout.getChunksDifferent() == 0);
    }

    @Test
    public void testRange() {
        Range<Long> r = new Range<Long>(10L, 20L);
        assertEquals(r.getLower().longValue(), 10L);
        assertEquals(r.getUpper().longValue(), 20L);
    }

    @Test
    public void testCreateOp() throws Exception {
        // setup a valid config
        ConfigExtractor extractor = getTestConfig(false);
        final Path fn = new Path(getTestFile().getCanonicalPath());
        CreateOp op = new CreateOp(extractor, rnd) {
            protected Path getCreateFile() {
                return fn;
            }
        };
        runOperationOk(extractor, op, true);
    }

    @Test
    public void testOpFailures() throws Exception {
        ConfigExtractor extractor = getTestConfig(false);
        final Path fn = new Path(getImaginaryFile().getCanonicalPath());
        ReadOp rop = new ReadOp(extractor, rnd) {
            protected Path getReadFile() {
                return fn;
            }
        };
        runOperationBad(extractor, rop);

        DeleteOp dop = new DeleteOp(extractor, rnd) {
            protected Path getDeleteFile() {
                return fn;
            }
        };
        runOperationBad(extractor, dop);

        RenameOp reop = new RenameOp(extractor, rnd) {
            protected SrcTarget getRenames() {
                return new SrcTarget(fn, fn);
            }
        };
        runOperationBad(extractor, reop);

        AppendOp aop = new AppendOp(extractor, rnd) {
            protected Path getAppendFile() {
                return fn;
            }
        };

        runOperationBad(extractor, aop);
    }

    private void runOperationBad(ConfigExtractor cfg, Operation op) throws Exception {
        FileSystem fs = FileSystem.get(cfg.getConfig());
        List<OperationOutput> data = op.run(fs);
        assertTrue(!data.isEmpty());
        boolean foundFail = false;
        for (OperationOutput d : data) {
            if (d.getMeasurementType().equals(ReportWriter.FAILURES)) {
                foundFail = true;
            }
            if (d.getMeasurementType().equals(ReportWriter.NOT_FOUND)) {
                foundFail = true;
            }
        }
        assertTrue(foundFail);
    }

    private void runOperationOk(ConfigExtractor cfg, Operation op, boolean checkOk) throws Exception {
        FileSystem fs = FileSystem.get(cfg.getConfig());
        List<OperationOutput> data = op.run(fs);
        assertTrue(!data.isEmpty());
        if (checkOk) {
            boolean foundSuc = false;
            boolean foundOpCount = false;
            boolean foundTime = false;
            for (OperationOutput d : data) {
                assertTrue(!d.getMeasurementType().equals(ReportWriter.FAILURES));
                if (d.getMeasurementType().equals(ReportWriter.SUCCESSES)) {
                    foundSuc = true;
                }
                if (d.getMeasurementType().equals(ReportWriter.OP_COUNT)) {
                    foundOpCount = true;
                }
                if (d.getMeasurementType().equals(ReportWriter.OK_TIME_TAKEN)) {
                    foundTime = true;
                }
            }
            assertTrue(foundSuc);
            assertTrue(foundOpCount);
            assertTrue(foundTime);
        }
    }

    @Test
    public void testDelete() throws Exception {
        ConfigExtractor extractor = getTestConfig(false);
        final Path fn = new Path(getTestFile().getCanonicalPath());
        // ensure file created before delete
        CreateOp op = new CreateOp(extractor, rnd) {
            protected Path getCreateFile() {
                return fn;
            }
        };
        runOperationOk(extractor, op, true);
        // now delete
        DeleteOp dop = new DeleteOp(extractor, rnd) {
            protected Path getDeleteFile() {
                return fn;
            }
        };
        runOperationOk(extractor, dop, true);
    }

    @Test
    public void testRename() throws Exception {
        ConfigExtractor extractor = getTestConfig(false);
        final Path src = new Path(getTestFile().getCanonicalPath());
        final Path tgt = new Path(getTestRenameFile().getCanonicalPath());
        // ensure file created before rename
        CreateOp op = new CreateOp(extractor, rnd) {
            protected Path getCreateFile() {
                return src;
            }
        };
        runOperationOk(extractor, op, true);
        RenameOp rop = new RenameOp(extractor, rnd) {
            protected SrcTarget getRenames() {
                return new SrcTarget(src, tgt);
            }
        };
        runOperationOk(extractor, rop, true);
    }

    @Test
    public void testMRFlow() throws Exception {
        ConfigExtractor extractor = getTestConfig(false);
        SliveTest s = new SliveTest(getBaseConfig());
        int ec = ToolRunner.run(s, getTestArgs(false));
        assertTrue(ec == 0);
        String resFile = extractor.getResultFile();
        File fn = new File(resFile);
        assertTrue(fn.exists());
        // can't validate completely since operations may fail (mainly anyone but
        // create +mkdir) since they may not find there files
    }

    @Test
    public void testRead() throws Exception {
        ConfigExtractor extractor = getTestConfig(false);
        final Path fn = new Path(getTestFile().getCanonicalPath());
        // ensure file created before read
        CreateOp op = new CreateOp(extractor, rnd) {
            protected Path getCreateFile() {
                return fn;
            }
        };
        runOperationOk(extractor, op, true);
        ReadOp rop = new ReadOp(extractor, rnd) {
            protected Path getReadFile() {
                return fn;
            }
        };
        runOperationOk(extractor, rop, true);
    }

    @Test
    public void testSleep() throws Exception {
        ConfigExtractor extractor = getTestConfig(true);
        SleepOp op = new SleepOp(extractor, rnd);
        runOperationOk(extractor, op, true);
    }

    @Test
    public void testList() throws Exception {
        // ensure dir made
        ConfigExtractor extractor = getTestConfig(false);
        final Path dir = new Path(getTestDir().getCanonicalPath());
        MkdirOp op = new MkdirOp(extractor, rnd) {
            protected Path getDirectory() {
                return dir;
            }
        };
        runOperationOk(extractor, op, true);
        // list it
        ListOp lop = new ListOp(extractor, rnd) {
            protected Path getDirectory() {
                return dir;
            }
        };
        runOperationOk(extractor, lop, true);
    }

    @Test
    public void testBadChunks() throws Exception {
        File fn = getTestFile();
        int byteAm = 10000;
        FileOutputStream fout = new FileOutputStream(fn);
        byte[] bytes = new byte[byteAm];
        rnd.nextBytes(bytes);
        fout.write(bytes);
        fout.close();
        // attempt to read it
        DataVerifier vf = new DataVerifier();
        VerifyOutput vout = new VerifyOutput(0, 0, 0, 0);
        DataInputStream in = null;
        try {
            in = new DataInputStream(new FileInputStream(fn));
            vout = vf.verifyFile(byteAm, in);
        } catch (Exception e) {

        } finally {
            if (in != null)
                in.close();
        }
        assertTrue(vout.getChunksSame() == 0);
    }

    @Test
    public void testMkdir() throws Exception {
        ConfigExtractor extractor = getTestConfig(false);
        final Path dir = new Path(getTestDir().getCanonicalPath());
        MkdirOp op = new MkdirOp(extractor, rnd) {
            protected Path getDirectory() {
                return dir;
            }
        };
        runOperationOk(extractor, op, true);
    }

    @Test
    public void testSelector() throws Exception {
        ConfigExtractor extractor = getTestConfig(false);
        RouletteSelector selector = new RouletteSelector(rnd);
        List<OperationWeight> sList = new LinkedList<OperationWeight>();
        Operation op = selector.select(sList);
        assertTrue(op == null);
        CreateOp cop = new CreateOp(extractor, rnd);
        sList.add(new OperationWeight(cop, 1.0d));
        AppendOp aop = new AppendOp(extractor, rnd);
        sList.add(new OperationWeight(aop, 0.01d));
        op = selector.select(sList);
        assertTrue(op == cop);
    }

    @Test
    public void testAppendOp() throws Exception {
        // setup a valid config
        ConfigExtractor extractor = getTestConfig(false);
        // ensure file created before append
        final Path fn = new Path(getTestFile().getCanonicalPath());
        CreateOp op = new CreateOp(extractor, rnd) {
            protected Path getCreateFile() {
                return fn;
            }
        };
        runOperationOk(extractor, op, true);
        // local file system (ChecksumFileSystem) currently doesn't support append -
        // but we'll leave this test here anyways but can't check the results..
        AppendOp aop = new AppendOp(extractor, rnd) {
            protected Path getAppendFile() {
                return fn;
            }
        };
        runOperationOk(extractor, aop, false);
    }
}