Subversion Repositories mkgmap

Rev

Rev 4542 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Copyright (C) 2008 Steve Ratcliffe
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *
 * Author: Steve Ratcliffe
 * Create date: 10-Jan-2009
 */

package func.lib;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.TimeUnit;

import uk.me.parabola.imgfmt.Utils;
import uk.me.parabola.mkgmap.general.LevelInfo;
import uk.me.parabola.mkgmap.main.Main;
import uk.me.parabola.mkgmap.osmstyle.RuleFileReader;
import uk.me.parabola.mkgmap.osmstyle.RuleSet;
import uk.me.parabola.mkgmap.osmstyle.StyleFileLoader;
import uk.me.parabola.mkgmap.reader.osm.FeatureKind;

import static org.junit.Assert.*;

/**
 * Useful routines to use during the functional tests.
 *
 * @author Steve Ratcliffe
 */

public class TestUtils {
        private static final List<String> files = new ArrayList<>();
        private static final Deque<Closeable> open = new ArrayDeque<>();

        static {
                files.add(Args.DEF_MAP_FILENAME);
                files.add(Args.DEF_MAP_FILENAME2);
                files.add(Args.DEF_GMAPSUPP_FILENAME);
                files.add(Args.DEF_TDB_FILENAME);

                Runnable r = new Runnable() {
                        public void run() {
                                deleteOutputFiles();
                        }
                };
                Thread t = new Thread(r);
                Runtime.getRuntime().addShutdownHook(t);
        }

        /**
         * Delete output files that were created by the tests.
         * Used to clean up before/after a test.
         */

        public static void deleteOutputFiles() {
                List<String> failList = new ArrayList<>();
                for (String fname : files) {
                        File f = new File(fname);

                        if (f.exists()) {
                                if (!f.delete())
                                        failList.add(f.getName());
                        }
                }

                assertEquals("Files not deleted", Collections.emptyList(), failList);
        }

        public static void closeFiles() {
                while (!open.isEmpty())
                        Utils.closeFile(open.remove());
        }

        public static void registerFile(String ... names) {
                Collections.addAll(files, names);
        }

        public static void registerFile(Closeable... files) {
                Collections.addAll(open, files);
        }

        /**
         * Run with a single argument.  The standard arguments are added first.
         * @param arg The argument.
         */

        public static Outputs run(String arg) {
                return run(new String[] {arg});
        }

        /**
         * Run with the given args.  Some standard arguments are added first.
         *
         * To run without the standard args, use runRaw().
         * @param in The arguments to use.
         */

        public static Outputs run(String ... in) {
                List<String> args = new ArrayList<>(Arrays.asList(in));
                args.add(0, Args.TEST_STYLE_ARG);

                OutputStream outsink = new ByteArrayOutputStream();
                PrintStream out = new PrintStream(outsink);

                OutputStream errsink = new ByteArrayOutputStream();
                PrintStream err = new PrintStream(errsink);

                PrintStream origout = System.out;
                PrintStream origerr = System.err;

                try {
                        System.setOut(out);
                        System.setErr(err);
                        Main.mainNoSystemExit(args.toArray(new String[args.size()]));
                } finally {
                        out.close();
                        err.close();
                        System.setOut(origout);
                        System.setErr(origerr);
                }

                return new Outputs(outsink.toString(), errsink.toString());
        }

        /**
         * Run with the given args as a new process.  Some standard arguments are added first.
         *
         * @param in The arguments to use.
         */

        public static Outputs runAsProcess(String ... in) {
        List<String> args = new ArrayList<>(Arrays.asList(
                "java",
                "-classpath",
                "build/classes" + File.pathSeparator + "lib/compile/*",
                "uk.me.parabola.mkgmap.main.Main",
                Args.TEST_STYLE_ARG
        ));
        args.addAll(Arrays.asList(in));
                ProcessBuilder pb = new ProcessBuilder(args);
                StringBuilder outBuilder = new StringBuilder();
                StringBuilder errBuilder = new StringBuilder();
                try {
                        Process process = pb.start();
                        try (BufferedReader errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                                 BufferedReader outputStream = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                                while (true) {
                                        getStreamOutput(outputStream, outBuilder);
                                        getStreamOutput(errorStream, errBuilder);
                                        if (process.waitFor(1, TimeUnit.MILLISECONDS)) {
                                                getStreamOutput(outputStream, outBuilder);
                                                getStreamOutput(errorStream, errBuilder);
                                                break;
                                        }
                                }
                        }
                } catch (IOException e) {
                        // do nothing
                } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                }
                return new Outputs(outBuilder.toString(), errBuilder.toString());
        }

        private static void getStreamOutput(BufferedReader stream, StringBuilder stringBuilder) throws IOException {
                char[] buff = new char[100000];
                while (stream.ready()) {
                        int count = stream.read(buff);
                        if (count > 0)
                                stringBuilder.append(buff, 0, count);
                }
        }

        /**
         * Create a rule set out of a string.  The string is processed
         * as if it were in a file and the levels spec had been set.
         */

        public static RuleSet makeRuleSet(String in) {
                StringStyleFileLoader loader = new StringStyleFileLoader(new String[][] {
                                {"lines", in}
                });

                return makeRuleSet(loader);
        }

        /**
         * Make a rule set from the "lines" file of the given StyleFileLoader.
         *
         * @param loader This will be used to load the file 'lines'. If that file includes any other file, then it
         * should accessible from the loader too.
         *
         * @return A rule set for lines.
         */

        public static RuleSet makeRuleSet(StyleFileLoader loader) {
                RuleSet rs = new RuleSet();
                RuleFileReader rr = new RuleFileReader(FeatureKind.POLYLINE, LevelInfo.createFromString("0:24 1:20 2:18 3:16 4:14"),
                                rs, false, null);
                try {
                        rr.load(loader, "lines");
                } catch (FileNotFoundException e) {
                        throw new AssertionError("Failed to open file: lines");
                }
                return rs;
        }

}