private static void Solve(Action<CubeConfiguration<FaceColour>> assertFunc, bool runAllStepsUpToThis = false)
        {
            var configuration = ConfigurationGenerator.GenerateRandomConfiguration(5, 100);
            var solver = new UpperAndDownFaceTredgesSolver();

            try
            {
                if (runAllStepsUpToThis)
                {
                    new AllInnerCrossesSolver().Solve(configuration).Wait();
                    new InnerSquareSolver().Solve(configuration).Wait();
                }

                solver.Solve(configuration).Wait(TestRunner.Timeout);
                assertFunc(configuration);
            }
            catch
            {
                var f = configuration.Faces[FaceType.Front].Items;
                var b = configuration.Faces[FaceType.Back].Items;
                var l = configuration.Faces[FaceType.Left].Items;
                var r = configuration.Faces[FaceType.Right].Items;
                var u = configuration.Faces[FaceType.Upper].Items;
                var d = configuration.Faces[FaceType.Down].Items;
                throw;
            }
        }
        // TODO: MAYBE RETURN THINGS IN SECTIONS?
        public override async Task<IEnumerable<IRotation>> Solve(CubeConfiguration<FaceColour> configuration)
        {
            await base.Solve(configuration).ConfigureAwait(false);

            m_configuration = configuration;

            var solution = new List<IRotation>();

            var cubeRotation = await CommonActions.PositionOnBottom(m_configuration, FaceColour.White).ConfigureAwait(false);

            if (cubeRotation != null)
                solution.Add(cubeRotation);

            var innerCrossesSolver = new AllInnerCrossesSolver();
            var stepsToSolveCrosses = await innerCrossesSolver.Solve(m_configuration).ConfigureAwait(false);

            solution.AddRange(stepsToSolveCrosses);

            var innerSquareSolver = new InnerSquareSolver();
            var stepsToSolveSquares = await innerSquareSolver.Solve(m_configuration).ConfigureAwait(false);

            solution.AddRange(stepsToSolveSquares);

            var tredgeSolver = new UpperAndDownFaceTredgesSolver();
            var stepsToSolveTredges = await tredgeSolver.Solve(m_configuration).ConfigureAwait(false);

            solution.AddRange(stepsToSolveTredges);

            var middleTredgeSolver = new MiddleLayerTredgeSolver();
            var stepsToSolveMiddleLayerTredges = await middleTredgeSolver.Solve(configuration).ConfigureAwait(false);

            solution.AddRange(stepsToSolveMiddleLayerTredges);

            // TODO: INJECT A 3x3x3 solver in here so different ones can be used
            var threeByThreeByThreeSolver = new Size3.BeginerMethod
            {
                SkipChecks = true
            };
            var stepsToSolveReduced3X3X3 = await threeByThreeByThreeSolver.Solve(configuration).ConfigureAwait(false);

            solution.AddRange(stepsToSolveReduced3X3X3);

            return solution.Condense();
        }