com.squareup.luhnybin.Main.java Source code

Java tutorial

Introduction

Here is the source code for com.squareup.luhnybin.Main.java

Source

/*
 * Copyright (C) 2011 Square, Inc.
 *
 * 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.squareup.luhnybin;

import com.google.common.io.ByteStreams;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

/**
 * Runs the test suite against mask.sh.
 *
 * @author Bob Lee (bob@squareup.com)
 */
public class Main extends TestSuite {

    private static int testsPassed = 0;

    public static void main(String[] args) throws IOException {
        if (!new File("mask.sh").exists()) {
            System.err.println("Couldn't find 'mask.sh' in the current directory.");
            System.exit(1);
        }

        final int iterations;
        if (args.length > 0) {
            if (args.length > 1) {
                System.err.println("Usage: ./run.sh [iterations]");
                System.exit(1);
            }

            iterations = Integer.parseInt(args[0]);
            if (iterations < 1) {
                System.err.println("Iterations must be >= 1.");
                System.exit(1);
            }
        } else {
            iterations = 1;
        }

        final Executor executor = Executors.newCachedThreadPool(new ThreadFactory() {
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setDaemon(true);
                return thread;
            }
        });

        System.out.println("Running tests against mask.sh...");
        System.out.println();

        final LuhnyBinTests luhnyBinTests = new LuhnyBinTests();
        final Process process = new ProcessBuilder("sh", "mask.sh").start();

        // Copy error stream from child process.
        executor.execute(new Runnable() {
            public void run() {
                try {
                    ByteStreams.copy(process.getErrorStream(), System.err);
                } catch (IOException e) {
                    /* ignore */ }
            }
        });

        // Buffer output for maximum efficiency.
        final ByteArrayOutputStream bout = new ByteArrayOutputStream();
        luhnyBinTests.writeTo(bout);

        final OutputStream out = process.getOutputStream();
        final InputStream in = process.getInputStream();
        long start = System.nanoTime();
        try {
            // Time/iteration in ms.
            long[] times = new long[iterations];

            for (int i = 0; i < iterations; i++) {
                final boolean lastIteration = i == iterations - 1;

                long iterationStart = System.nanoTime();

                // Write in the background. Writing can block if the buffer fills up.
                executor.execute(new Runnable() {
                    public void run() {
                        try {
                            bout.writeTo(out);
                            out.flush();
                            if (lastIteration)
                                out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                            System.exit(1);
                        }
                    }
                });

                luhnyBinTests.check(in, new TestCase.Listener() {
                    public void testPassed(TestCase test) {
                        System.out.print('.');
                        if (++testsPassed % 80 == 0)
                            System.out.println();
                    }

                    public void testFailed(TestCase test, String actualInput) {
                        System.out.println('X');
                        System.out.println();
                        System.err.println("Test #" + test.index + " of " + luhnyBinTests.count + " failed:"
                                + "\n  Description:     " + test.description + "\n  Input:           "
                                + showBreaks(test.output) + "\n  Expected result: " + showBreaks(test.expectedInput)
                                + "\n  Actual result:   " + showBreaks(actualInput) + "\n");
                        process.destroy();
                        System.exit(1);
                    }
                });
                times[i] = (System.nanoTime() - iterationStart) / 1000;
            }

            long elapsed = (System.nanoTime() - start) / 1000000;

            System.out.println();
            if (testsPassed % 80 != 0)
                System.out.println();
            System.out.println("Tests passed!");
            System.out.println();
            System.out.printf("Total time:   %,dms%n", elapsed);

            if (iterations > 1) {
                long sum = 0;
                for (long time : times)
                    sum += time;

                Arrays.sort(times);
                System.out.printf("Mean time:    %,dus%n", sum / times.length);
                System.out.printf("Median time:  %,dus%n", times[times.length / 2]);
                System.out.printf("Fastest time: %,dus%n", times[0]);
            }

            System.out.println();
            process.destroy();
            System.exit(0);
        } catch (EOFException e) {
            System.err.println("Error: mask.sh didn't send the expected amount of output.");
            process.destroy();
            System.exit(1);
        }
    }

    static String showBreaks(String s) {
        return s.replace("\n", "\\n").replace("\r", "\\r");
    }
}