     
     override func setUp() {
         super.setUp()
-        transitionContextsStackImpl = TransitionContextsStackImpl()
+        __stackImpl = TransitionContextsStackImpl()
         
         autoZombieContext = createCompletedTransitionContext(
             sourceViewController: nil,

//
//  Navigation_Prototype_Tests.swift
//  Navigation-Prototype-Tests
//
//  Created by Тимур Юсипов on 10/02/16.
//  Copyright © 2016 Тимур Юсипов. All rights reserved.
//

import XCTest

private class DummyTransitionsHandler: TransitionsHandler {

            targetTransitionsHandler: dummyTransitionsHandler)
    }
    
    func subtest_StackToBeEmptyAtStart(__stackImpl: TransitionContextsStack) {
        XCTAssertNil(__stackImpl.first, "в начале стек должен быть пуст")
        XCTAssertNil(__stackImpl.last, "в начале стек должен быть пуст")
    }
    
    func test_AddingZombie() {
        guard let __stackImpl = __stackImpl
            else { XCTAssert(false); return }
        guard let autoZombieContext = autoZombieContext
            else { XCTAssert(false); return }

        subtest_StackToBeEmptyAtStart(__stackImpl)

        // append zombie. must still be empty
        __stackImpl.append(autoZombieContext)
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingZombie:autoZombieContext
        )
    }
    
    func subtest_Stack(__stackImpl: TransitionContextsStack,
        toBeEmptyAfterAddingZombie autoZombieContext: CompletedTransitionContext)
    {
        XCTAssertNil(__stackImpl.first, "при добавлении зомби, он должен удаляться при любом mutating'e или чтении стека. стек должен быть пуст")
        XCTAssertNil(__stackImpl.last, "при добавлении зомби, он должен удаляться при любом mutating'e или чтении стека. стек должен быть пуст")
        XCTAssertNil(__stackImpl[autoZombieContext.transitionId], "при добавлении зомби, он должен удаляться при любом mutating'e или чтении стека. стек должен быть пуст")
        XCTAssertNil(__stackImpl.preceding(transitionId:autoZombieContext.transitionId), "при добавлении зомби, он должен удаляться при любом mutating'e или чтении стека. стек должен быть пуст")
        XCTAssertNil(__stackImpl.popTo(transitionId: autoZombieContext.transitionId), "при добавлении зомби, он должен удаляться при любом mutating'e или чтении стека. стек должен быть пуст")
    }
    
    func test_AddingNotZombie() {
        guard let __stackImpl = __stackImpl
            else { XCTAssert(false); return }
        guard let neverZombieContext1 = neverZombieContext1
            else { XCTAssert(false); return }
        
        subtest_StackToBeEmptyAtStart(__stackImpl)
        
        // append not zombie. must become not empty
        __stackImpl.append(neverZombieContext1)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1
        )
    }
    
    func subtest_Stack(__stackImpl: TransitionContextsStack,
        toBeNotEmptyAfterAddingNotZombie1 neverZombieContext1: CompletedTransitionContext)
    {
        XCTAssertNotNil(__stackImpl.first, "при добавлении не зомби, он не должен удаляться из стека, пока жив targetViewController")
        XCTAssertNotNil(__stackImpl.last, "при добавлении не зомби, он не должен удаляться из стека, пока жив targetViewController")
        XCTAssertEqual(__stackImpl.first!, __stackImpl.last!)
        XCTAssertEqual(__stackImpl.first!.transitionId, neverZombieContext1.transitionId, "вставили не зомби. должны достать его же")
        XCTAssertNotNil(__stackImpl[neverZombieContext1.transitionId], "при добавлении не зомби, он не должен удаляться из стека, пока жив targetViewController")
        XCTAssertEqual(__stackImpl[neverZombieContext1.transitionId]!.transitionId, neverZombieContext1.transitionId, "вставили не зомби. должны достать его же")
        XCTAssertNil(__stackImpl.preceding(transitionId:neverZombieContext1.transitionId), "добавили одну запись. перед ней нет других записей")
        XCTAssertNil(__stackImpl.popTo(transitionId: neverZombieContext1.transitionId), "добавили одну запись. после нее нет других записей")
    }
    
    func test_AddingZombie_AddingNotZombie() {
        guard let __stackImpl = __stackImpl
            else { XCTAssert(false); return }
        guard let autoZombieContext = autoZombieContext
            else { XCTAssert(false); return }
        guard let neverZombieContext1 = neverZombieContext1
            else { XCTAssert(false); return }
        
        subtest_StackToBeEmptyAtStart(__stackImpl)
        
        // append zombie. must still be empty
        __stackImpl.append(autoZombieContext)
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingZombie: autoZombieContext
        )

        // append not zombie. must become not empty
        __stackImpl.append(neverZombieContext1)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1
        )
    }
    
    func test_AddingZombie_AddingNotZombie_PoppingNotZombie() {
        guard let __stackImpl = __stackImpl
            else { XCTAssert(false); return }
        guard let autoZombieContext = autoZombieContext
            else { XCTAssert(false); return }
        guard let neverZombieContext1 = neverZombieContext1
            else { XCTAssert(false); return }
        
        subtest_StackToBeEmptyAtStart(__stackImpl)
        
        // append zombie. must still be empty
        __stackImpl.append(autoZombieContext)
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingZombie: autoZombieContext
        )
        
        // append not zombie 1. must become not empty
        __stackImpl.append(neverZombieContext1)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1
        )

        // pop via technique 1. must become empty again
        let neverZombie1_popped = __stackImpl.popLast()
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingNotZombie1: neverZombieContext1,
            andPoppingNeverZombie1: neverZombie1_popped
        )
    }
    
    func subtest_Stack(__stackImpl: TransitionContextsStack,
        toBeEmptyAfterAddingNotZombie1 neverZombieContext1: CompletedTransitionContext,
        andPoppingNeverZombie1 neverZombie1_popped: RestoredTransitionContext?)
    {
        XCTAssertNotNil(neverZombie1_popped, "при добавлении не зомби, он не должен удаляться из стека, пока жив targetViewController")
        XCTAssertEqual(neverZombie1_popped!.transitionId, neverZombieContext1.transitionId, "вставили не зомби. должны достать его же")
        XCTAssertNil(__stackImpl.first, "один append, один pop. должно быть пусто")
        XCTAssertNil(__stackImpl.last, "один append, один pop. должно быть пусто")
        XCTAssertNil(__stackImpl[neverZombieContext1.transitionId], "один append, один pop. должно быть пусто")
        XCTAssertNil(__stackImpl.preceding(transitionId:neverZombieContext1.transitionId), "один append, один pop. должно быть пусто")
        XCTAssertNil(__stackImpl.popTo(transitionId: neverZombieContext1.transitionId), "один append, один pop. должно быть пусто")
    }
    
    func test_AddingZombie_AddingNotZombie_AddingNotZombie2() {
        guard let __stackImpl = __stackImpl
            else { XCTAssert(false); return }
        guard let autoZombieContext = autoZombieContext
            else { XCTAssert(false); return }
        guard let neverZombieContext1 = neverZombieContext1
            else { XCTAssert(false); return }
        guard let neverZombieContext2 = neverZombieContext2
            else { XCTAssert(false); return }
        
        subtest_StackToBeEmptyAtStart(__stackImpl)
        
        // append not zombie. must still be empty
        __stackImpl.append(autoZombieContext)
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingZombie: autoZombieContext
        )
        
        // append not zombie 1. must become not empty
        __stackImpl.append(neverZombieContext1)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1
        )
        
        // append not zombie 2. must remain not empty
        __stackImpl.append(neverZombieContext2)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1,
            andAddingNotZombie2: neverZombieContext2
        )
    }
    
    func subtest_Stack(__stackImpl: TransitionContextsStack,
        toBeNotEmptyAfterAddingNotZombie1 neverZombieContext1: CompletedTransitionContext,
        andAddingNotZombie2 neverZombieContext2: CompletedTransitionContext)
    {
        XCTAssertNotNil(__stackImpl.first, "при добавлении не зомби, он не должен удаляться из стека, пока жив targetViewController")
        XCTAssertNotNil(__stackImpl.last, "при добавлении не зомби, он не должен удаляться из стека, пока жив targetViewController")
        XCTAssertNotEqual(__stackImpl.first!, __stackImpl.last!)
        XCTAssertEqual(__stackImpl.first!.transitionId, neverZombieContext1.transitionId, "вставили первого не зомби первым. он должен быть первым")
        XCTAssertEqual(__stackImpl.last!.transitionId, neverZombieContext2.transitionId, "вставили второго не зомби вторым. он должен быть последним")
        XCTAssertNotNil(__stackImpl[neverZombieContext1.transitionId], "при добавлении не зомби, он не должен удаляться из стека, пока жив targetViewController")
        XCTAssertEqual(__stackImpl[neverZombieContext1.transitionId]!.transitionId, neverZombieContext1.transitionId, "вставили не зомби. должны достать его же")
        XCTAssertNil(__stackImpl.preceding(transitionId:neverZombieContext1.transitionId), "перед первым не зомби никого не должно быть")
        XCTAssertNotNil(__stackImpl[neverZombieContext2.transitionId], "при добавлении не зомби, он не должен удаляться из стека, пока жив targetViewController")
        XCTAssertEqual(__stackImpl[neverZombieContext2.transitionId]!.transitionId, neverZombieContext2.transitionId, "вставили не зомби. должны достать его же")
        XCTAssertNotNil(__stackImpl.preceding(transitionId:neverZombieContext2.transitionId), "перед вторым не зомби должен идти первый")
        XCTAssertEqual(__stackImpl.preceding(transitionId:neverZombieContext2.transitionId)?.transitionId, neverZombieContext1.transitionId, "перед вторым не зомби должен идти первый")
        XCTAssertNil(__stackImpl.popTo(transitionId: neverZombieContext2.transitionId), "после второго не зомби никого не должно быть")
    }
    
    func test_AddingZombie_AddingNotZombie_AddingNotZombie2_PoppingNotZombie2ViaTechnique1() {
        guard let __stackImpl = __stackImpl
            else { XCTAssert(false); return }
        guard let autoZombieContext = autoZombieContext
            else { XCTAssert(false); return }
        guard let neverZombieContext1 = neverZombieContext1
            else { XCTAssert(false); return }
        guard let neverZombieContext2 = neverZombieContext2
            else { XCTAssert(false); return }
        
        subtest_StackToBeEmptyAtStart(__stackImpl)
        
        // append not zombie. must still be empty
        __stackImpl.append(autoZombieContext)
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingZombie: autoZombieContext
        )
        
        // append not zombie 1. must become not empty
        __stackImpl.append(neverZombieContext1)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1
        )
        
        // append not zombie 2. must remain not empty
        __stackImpl.append(neverZombieContext2)
        subtest_Stack(__stackImpl, 
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1,
            andAddingNotZombie2: neverZombieContext2
        )
        
        // pop via technique 1. must remain not empty
        let neverZombie2_popped = __stackImpl.popLast()
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1,
            addingNotZombie2: neverZombieContext2,
            andPoppingNeverZombie2ViaTechnique1: neverZombie2_popped
        )
    }
    
    func subtest_Stack(__stackImpl: TransitionContextsStack,
        toBeNotEmptyAfterAddingNotZombie1 neverZombieContext1: CompletedTransitionContext,
        addingNotZombie2 neverZombieContext2: CompletedTransitionContext,
        andPoppingNeverZombie2ViaTechnique1 neverZombie2_popped: RestoredTransitionContext?)
    {
        XCTAssertNotNil(neverZombie2_popped, "после первого не зомби должен был быть второй не зомби")
        XCTAssertEqual(neverZombie2_popped!.transitionId, neverZombieContext2.transitionId, "после первого не зомби должен был быть второй не зомби")
        XCTAssertNil(__stackImpl.popTo(transitionId: neverZombieContext1.transitionId), "после первого не зомби уже никого не должно быть")
        XCTAssertNil(__stackImpl[neverZombieContext2.transitionId], "достали второго не зомби. больше его не должно быть в стеке")
        XCTAssertNotNil(__stackImpl[neverZombieContext1.transitionId], "первый должен остаться в стеке")
        XCTAssertEqual(__stackImpl[neverZombieContext1.transitionId]!.transitionId, neverZombieContext1.transitionId, "первый должен остаться в стеке")
        XCTAssertNotNil(__stackImpl.first, "первый должен остаться в стеке")
        XCTAssertNotNil(__stackImpl.last, "первый должен остаться в стеке")
        XCTAssertEqual(__stackImpl.first!, __stackImpl.last!, "первый должен остаться в стеке")
        XCTAssertEqual(__stackImpl.first!.transitionId, neverZombieContext1.transitionId, "первый должен остаться в стеке")
    }
    
    func test_AddingZombie_AddingNotZombie_AddingNotZombie2_PoppingNotZombie2ViaTechnique2() {
        guard let __stackImpl = __stackImpl
            else { XCTAssert(false); return }
        guard let autoZombieContext = autoZombieContext
            else { XCTAssert(false); return }
        guard let neverZombieContext1 = neverZombieContext1
            else { XCTAssert(false); return }
        guard let neverZombieContext2 = neverZombieContext2
            else { XCTAssert(false); return }
        
        subtest_StackToBeEmptyAtStart(__stackImpl)
        
        // append not zombie. must still be empty
        __stackImpl.append(autoZombieContext)
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingZombie: autoZombieContext
        )
        
        // append not zombie 1. must become not empty
        __stackImpl.append(neverZombieContext1)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1
        )
        
        // append not zombie 2. must remain not empty
        __stackImpl.append(neverZombieContext2)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1,
            andAddingNotZombie2: neverZombieContext2
        )
        
        // pop via technique 2. must remain not empty
        let neverZombie2_poppedAsArray = __stackImpl.popTo(transitionId: neverZombieContext1.transitionId)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1,
            addingNotZombie2: neverZombieContext2,
            andPoppingNeverZombie2ViaTechnique2: neverZombie2_poppedAsArray
        )
    }
    
    func subtest_Stack(__stackImpl: TransitionContextsStack,
        toBeNotEmptyAfterAddingNotZombie1 neverZombieContext1: CompletedTransitionContext,
        addingNotZombie2 neverZombieContext2: CompletedTransitionContext,
        andPoppingNeverZombie2ViaTechnique2 neverZombie2_poppedAsArray: [RestoredTransitionContext]?)
    {
    
        XCTAssertNotNil(neverZombie2_poppedAsArray, "после первого не зомби должен был быть второй не зомби")
        XCTAssertEqual(neverZombie2_poppedAsArray!.count, 1, "после первого не зомби должен был быть только второй не зомби")
        XCTAssertEqual(neverZombie2_poppedAsArray!.last!.transitionId, neverZombieContext2.transitionId, "после первого не зомби должен был быть второй не зомби")
        XCTAssertNil(__stackImpl.popTo(transitionId: neverZombieContext1.transitionId), "после первого не зомби уже никого не должно быть")
        XCTAssertNil(__stackImpl[neverZombieContext2.transitionId], "достали второго не зомби. больше его не должно быть в стеке")
        XCTAssertNotNil(__stackImpl[neverZombieContext1.transitionId], "первый должен остаться в стеке")
        XCTAssertEqual(__stackImpl[neverZombieContext1.transitionId]!.transitionId, neverZombieContext1.transitionId, "первый должен остаться в стеке")
        XCTAssertNotNil(__stackImpl.first, "первый должен остаться в стеке")
        XCTAssertNotNil(__stackImpl.last, "первый должен остаться в стеке")
        XCTAssertEqual(__stackImpl.first!, __stackImpl.last!, "первый должен остаться в стеке")
        XCTAssertEqual(__stackImpl.first!.transitionId, neverZombieContext1.transitionId, "первый должен остаться в стеке")
    }
    
    func test_AddingZombie_AddingNotZombie_AddingNotZombie2_PoppingNotZombie2ViaTechnique1_PoppingNotZombie1ViaTechnique1() {
        guard let __stackImpl = __stackImpl
            else { XCTAssert(false); return }
        guard let autoZombieContext = autoZombieContext
            else { XCTAssert(false); return }
        guard let neverZombieContext1 = neverZombieContext1
            else { XCTAssert(false); return }
        guard let neverZombieContext2 = neverZombieContext2
            else { XCTAssert(false); return }

        subtest_StackToBeEmptyAtStart(__stackImpl)
        
        // append not zombie. must still be empty
        __stackImpl.append(autoZombieContext)
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingZombie: autoZombieContext
        )
        
        // append not zombie 1. must become not empty
        __stackImpl.append(neverZombieContext1)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1
        )
        
        // append not zombie 2. must remain not empty
        __stackImpl.append(neverZombieContext2)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1,
            andAddingNotZombie2: neverZombieContext2
        )
        
        // pop not zombie 2 via technique 1. must remain not empty
        let neverZombie2_popped = __stackImpl.popLast()
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1,
            addingNotZombie2: neverZombieContext2,
            andPoppingNeverZombie2ViaTechnique1: neverZombie2_popped
        )
        
        // pop not zombie 1 via technique 1. must become empty again
        let neverZombie1_popped = __stackImpl.popLast()
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingNotZombie1: neverZombieContext1,
            addingNotZombie2: neverZombieContext2,
            poppingNotZombie2AndPoppingNotZombie1: neverZombie1_popped
        )
    }
    
    func test_AddingZombie_AddingNotZombie_AddingNotZombie2_PoppingNotZombie2ViaTechnique2_PoppingNotZombie1ViaTechnique1() {
        guard let __stackImpl = __stackImpl
            else { XCTAssert(false); return }
        guard let autoZombieContext = autoZombieContext
            else { XCTAssert(false); return }
        guard let neverZombieContext1 = neverZombieContext1
            else { XCTAssert(false); return }
        guard let neverZombieContext2 = neverZombieContext2
            else { XCTAssert(false); return }
        
        subtest_StackToBeEmptyAtStart(__stackImpl)
        
        // append not zombie. must still be empty
        __stackImpl.append(autoZombieContext)
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingZombie: autoZombieContext
        )
        
        // append not zombie 1. must become not empty
        __stackImpl.append(neverZombieContext1)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1
        )
        
        // append not zombie 2. must remain not empty
        __stackImpl.append(neverZombieContext2)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1,
            andAddingNotZombie2: neverZombieContext2
        )
        
        // pop via technique 2. must remain not empty
        let neverZombie2_poppedAsArray = __stackImpl.popTo(transitionId: neverZombieContext1.transitionId)
        subtest_Stack(__stackImpl,
            toBeNotEmptyAfterAddingNotZombie1: neverZombieContext1,
            addingNotZombie2: neverZombieContext2,
            andPoppingNeverZombie2ViaTechnique2: neverZombie2_poppedAsArray
        )
        
        // pop not zombie 1 via technique 1. must become empty again
        let neverZombie1_popped = __stackImpl.popLast()
        subtest_Stack(__stackImpl,
            toBeEmptyAfterAddingNotZombie1: neverZombieContext1,
            addingNotZombie2: neverZombieContext2,
            poppingNotZombie2AndPoppingNotZombie1: neverZombie1_popped
        )
    }
    
    func subtest_Stack(__stackImpl: TransitionContextsStack,
        toBeEmptyAfterAddingNotZombie1 neverZombieContext1: CompletedTransitionContext,
        addingNotZombie2 neverZombieContext2: CompletedTransitionContext,
        poppingNotZombie2AndPoppingNotZombie1 neverZombie1_popped: RestoredTransitionContext?)
    {
        XCTAssertNotNil(neverZombie1_popped, "при добавлении не зомби, он не должен удаляться из стека, пока жив targetViewController")
        XCTAssertEqual(neverZombie1_popped!.transitionId, neverZombieContext1.transitionId, "вставили не зомби. должны достать его же")
        XCTAssertNil(__stackImpl.first, "два append'а, два pop'а. должно быть пусто")
        XCTAssertNil(__stackImpl.last, "два append'а, два pop'а. должно быть пусто")
        XCTAssertNil(__stackImpl[neverZombieContext1.transitionId], "два append'а, два pop'а. должно быть пусто")
