public void BasicThreading()
        {
            var pTxt =
                @"###########~
            #P..#..#..#~
            #..X#X...X#~
            ##..#OO#..#~
            ~#..#OO#..#~
            ~#..#OO#..##
            ~#X...X#X..#
            ~#..#..#...#
            ~###########";
            var puzzle = new Puzzle(pTxt);

            var exit = new ExitConditions()
            {
                Duration = TimeSpan.FromSeconds(60),
                StopOnSolution = true,
                TotalNodes = int.MaxValue,
                TotalDead = int.MaxValue
            };
            // arrange
            var solver = new MultiThreadedForwardReverseSolver();
            var command = new SolverCommand()
            {
                Puzzle = new Puzzle(puzzle),
                Report = Console.Out,
                ExitConditions = exit,
                Progress = new ConsoleProgressNotifier()
            };

            // act
            var result = solver.Init(command);
            solver.Solve(result);
            Assert.That(result, Is.Not.Null);
            Console.WriteLine(result.ExitDescription);
            Console.WriteLine(SolverHelper.Summary(result));
            result.ThrowErrors();

            // assert
            Assert.That(result, Is.Not.Null);
        }
        private SolverCommandResult PerformStandardTest(Puzzle puzzle, ExitConditions exit = null)
        {
            exit = exit ?? new ExitConditions()
            {
                Duration = TimeSpan.FromSeconds(60),
                StopOnSolution = true,
                TotalNodes = int.MaxValue,
                TotalDead = int.MaxValue
            };
            // arrange
            var solver = new SingleThreadedForwardReverseSolver();
            var command = new SolverCommand()
            {
                Puzzle = new Puzzle(puzzle),
                Report = Console.Out,
                ExitConditions = exit
            };

            // act
            var result = solver.Init(command);
            solver.Solve(result);
            Console.WriteLine(result.ExitDescription);
            Console.WriteLine(SolverHelper.Summary(result));
            result.ThrowErrors();

            // assert
            Assert.That(result, Is.Not.Null);

            Assert.That(result.HasSolution, Is.True);
            Assert.That(result.GetSolutions(), Is.Not.Null);
            Assert.That(result.GetSolutions(), Is.Not.Empty);

            foreach (var sol in result.GetSolutions())
            {
                Console.WriteLine("Path: {0}", sol);
                string error = null;
                Assert.That(SolverHelper.CheckSolution(command.Puzzle, sol, out error), "Solution is INVALID! " + error);
            }
            return result;
        }
        void PuzzleShouldHaveSolution(ISolver solver, Puzzle puzzle, ExitConditions exit = null, bool verbose = false)
        {
            if (exit == null)
            {
                exit = new ExitConditions()
                {
                    Duration = TimeSpan.FromSeconds(60),
                    StopOnSolution = true,
                    TotalNodes = int.MaxValue,
                    TotalDead = int.MaxValue
                };
            }
            var command = new SolverCommand()
            {
                Puzzle = puzzle,
                Report = Console.Out,
                Progress = new ConsoleProgressNotifier(),
                ExitConditions = exit
            };

            // act
            var result = solver.Init(command);
            solver.Solve(result);
            Console.WriteLine(result.ExitDescription);
            Console.WriteLine(SolverHelper.Summary(result));
            result.ThrowErrors();

            // assert
            Assert.That(result, Is.Not.Null);
            Assert.That(result.HasSolution, Is.True);

            foreach (var sol in result.GetSolutions())
            {
                Console.WriteLine("Path: {0}", sol);
                string error = null;

                Assert.That(SolverHelper.CheckSolution(command.Puzzle, sol, out error), "Solution is INVALID! "+error);
            }
        }