github.com/heimweh/terraform@v0.7.4/dag/dag_test.go (about)

     1  package dag
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"os"
     9  	"reflect"
    10  	"strings"
    11  	"sync"
    12  	"testing"
    13  
    14  	"github.com/hashicorp/terraform/helper/logging"
    15  )
    16  
    17  func TestMain(m *testing.M) {
    18  	flag.Parse()
    19  	if testing.Verbose() {
    20  		// if we're verbose, use the logging requested by TF_LOG
    21  		logging.SetOutput()
    22  	} else {
    23  		// otherwise silence all logs
    24  		log.SetOutput(ioutil.Discard)
    25  	}
    26  
    27  	os.Exit(m.Run())
    28  }
    29  
    30  func TestAcyclicGraphRoot(t *testing.T) {
    31  	var g AcyclicGraph
    32  	g.Add(1)
    33  	g.Add(2)
    34  	g.Add(3)
    35  	g.Connect(BasicEdge(3, 2))
    36  	g.Connect(BasicEdge(3, 1))
    37  
    38  	if root, err := g.Root(); err != nil {
    39  		t.Fatalf("err: %s", err)
    40  	} else if root != 3 {
    41  		t.Fatalf("bad: %#v", root)
    42  	}
    43  }
    44  
    45  func TestAcyclicGraphRoot_cycle(t *testing.T) {
    46  	var g AcyclicGraph
    47  	g.Add(1)
    48  	g.Add(2)
    49  	g.Add(3)
    50  	g.Connect(BasicEdge(1, 2))
    51  	g.Connect(BasicEdge(2, 3))
    52  	g.Connect(BasicEdge(3, 1))
    53  
    54  	if _, err := g.Root(); err == nil {
    55  		t.Fatal("should error")
    56  	}
    57  }
    58  
    59  func TestAcyclicGraphRoot_multiple(t *testing.T) {
    60  	var g AcyclicGraph
    61  	g.Add(1)
    62  	g.Add(2)
    63  	g.Add(3)
    64  	g.Connect(BasicEdge(3, 2))
    65  
    66  	if _, err := g.Root(); err == nil {
    67  		t.Fatal("should error")
    68  	}
    69  }
    70  
    71  func TestAyclicGraphTransReduction(t *testing.T) {
    72  	var g AcyclicGraph
    73  	g.Add(1)
    74  	g.Add(2)
    75  	g.Add(3)
    76  	g.Connect(BasicEdge(1, 2))
    77  	g.Connect(BasicEdge(1, 3))
    78  	g.Connect(BasicEdge(2, 3))
    79  	g.TransitiveReduction()
    80  
    81  	actual := strings.TrimSpace(g.String())
    82  	expected := strings.TrimSpace(testGraphTransReductionStr)
    83  	if actual != expected {
    84  		t.Fatalf("bad: %s", actual)
    85  	}
    86  }
    87  
    88  func TestAyclicGraphTransReduction_more(t *testing.T) {
    89  	var g AcyclicGraph
    90  	g.Add(1)
    91  	g.Add(2)
    92  	g.Add(3)
    93  	g.Add(4)
    94  	g.Connect(BasicEdge(1, 2))
    95  	g.Connect(BasicEdge(1, 3))
    96  	g.Connect(BasicEdge(1, 4))
    97  	g.Connect(BasicEdge(2, 3))
    98  	g.Connect(BasicEdge(2, 4))
    99  	g.Connect(BasicEdge(3, 4))
   100  	g.TransitiveReduction()
   101  
   102  	actual := strings.TrimSpace(g.String())
   103  	expected := strings.TrimSpace(testGraphTransReductionMoreStr)
   104  	if actual != expected {
   105  		t.Fatalf("bad: %s", actual)
   106  	}
   107  }
   108  
   109  func TestAcyclicGraphValidate(t *testing.T) {
   110  	var g AcyclicGraph
   111  	g.Add(1)
   112  	g.Add(2)
   113  	g.Add(3)
   114  	g.Connect(BasicEdge(3, 2))
   115  	g.Connect(BasicEdge(3, 1))
   116  
   117  	if err := g.Validate(); err != nil {
   118  		t.Fatalf("err: %s", err)
   119  	}
   120  }
   121  
   122  func TestAcyclicGraphValidate_cycle(t *testing.T) {
   123  	var g AcyclicGraph
   124  	g.Add(1)
   125  	g.Add(2)
   126  	g.Add(3)
   127  	g.Connect(BasicEdge(3, 2))
   128  	g.Connect(BasicEdge(3, 1))
   129  	g.Connect(BasicEdge(1, 2))
   130  	g.Connect(BasicEdge(2, 1))
   131  
   132  	if err := g.Validate(); err == nil {
   133  		t.Fatal("should error")
   134  	}
   135  }
   136  
   137  func TestAcyclicGraphValidate_cycleSelf(t *testing.T) {
   138  	var g AcyclicGraph
   139  	g.Add(1)
   140  	g.Add(2)
   141  	g.Connect(BasicEdge(1, 1))
   142  
   143  	if err := g.Validate(); err == nil {
   144  		t.Fatal("should error")
   145  	}
   146  }
   147  
   148  func TestAcyclicGraphAncestors(t *testing.T) {
   149  	var g AcyclicGraph
   150  	g.Add(1)
   151  	g.Add(2)
   152  	g.Add(3)
   153  	g.Add(4)
   154  	g.Add(5)
   155  	g.Connect(BasicEdge(0, 1))
   156  	g.Connect(BasicEdge(1, 2))
   157  	g.Connect(BasicEdge(2, 3))
   158  	g.Connect(BasicEdge(3, 4))
   159  	g.Connect(BasicEdge(4, 5))
   160  
   161  	actual, err := g.Ancestors(2)
   162  	if err != nil {
   163  		t.Fatalf("err: %#v", err)
   164  	}
   165  
   166  	expected := []Vertex{3, 4, 5}
   167  
   168  	if actual.Len() != len(expected) {
   169  		t.Fatalf("bad length! expected %#v to have len %d", actual, len(expected))
   170  	}
   171  
   172  	for _, e := range expected {
   173  		if !actual.Include(e) {
   174  			t.Fatalf("expected: %#v to include: %#v", expected, actual)
   175  		}
   176  	}
   177  }
   178  
   179  func TestAcyclicGraphDescendents(t *testing.T) {
   180  	var g AcyclicGraph
   181  	g.Add(1)
   182  	g.Add(2)
   183  	g.Add(3)
   184  	g.Add(4)
   185  	g.Add(5)
   186  	g.Connect(BasicEdge(0, 1))
   187  	g.Connect(BasicEdge(1, 2))
   188  	g.Connect(BasicEdge(2, 3))
   189  	g.Connect(BasicEdge(3, 4))
   190  	g.Connect(BasicEdge(4, 5))
   191  
   192  	actual, err := g.Descendents(2)
   193  	if err != nil {
   194  		t.Fatalf("err: %#v", err)
   195  	}
   196  
   197  	expected := []Vertex{0, 1}
   198  
   199  	if actual.Len() != len(expected) {
   200  		t.Fatalf("bad length! expected %#v to have len %d", actual, len(expected))
   201  	}
   202  
   203  	for _, e := range expected {
   204  		if !actual.Include(e) {
   205  			t.Fatalf("expected: %#v to include: %#v", expected, actual)
   206  		}
   207  	}
   208  }
   209  
   210  func TestAcyclicGraphWalk(t *testing.T) {
   211  	var g AcyclicGraph
   212  	g.Add(1)
   213  	g.Add(2)
   214  	g.Add(3)
   215  	g.Connect(BasicEdge(3, 2))
   216  	g.Connect(BasicEdge(3, 1))
   217  
   218  	var visits []Vertex
   219  	var lock sync.Mutex
   220  	err := g.Walk(func(v Vertex) error {
   221  		lock.Lock()
   222  		defer lock.Unlock()
   223  		visits = append(visits, v)
   224  		return nil
   225  	})
   226  	if err != nil {
   227  		t.Fatalf("err: %s", err)
   228  	}
   229  
   230  	expected := [][]Vertex{
   231  		{1, 2, 3},
   232  		{2, 1, 3},
   233  	}
   234  	for _, e := range expected {
   235  		if reflect.DeepEqual(visits, e) {
   236  			return
   237  		}
   238  	}
   239  
   240  	t.Fatalf("bad: %#v", visits)
   241  }
   242  
   243  func TestAcyclicGraphWalk_error(t *testing.T) {
   244  	var g AcyclicGraph
   245  	g.Add(1)
   246  	g.Add(2)
   247  	g.Add(3)
   248  	g.Add(4)
   249  	g.Connect(BasicEdge(4, 3))
   250  	g.Connect(BasicEdge(3, 2))
   251  	g.Connect(BasicEdge(2, 1))
   252  
   253  	var visits []Vertex
   254  	var lock sync.Mutex
   255  	err := g.Walk(func(v Vertex) error {
   256  		lock.Lock()
   257  		defer lock.Unlock()
   258  
   259  		if v == 2 {
   260  			return fmt.Errorf("error")
   261  		}
   262  
   263  		visits = append(visits, v)
   264  		return nil
   265  	})
   266  	if err == nil {
   267  		t.Fatal("should error")
   268  	}
   269  
   270  	expected := [][]Vertex{
   271  		{1},
   272  	}
   273  	for _, e := range expected {
   274  		if reflect.DeepEqual(visits, e) {
   275  			return
   276  		}
   277  	}
   278  
   279  	t.Fatalf("bad: %#v", visits)
   280  }
   281  
   282  func TestAcyclicGraph_ReverseDepthFirstWalk_WithRemoval(t *testing.T) {
   283  	var g AcyclicGraph
   284  	g.Add(1)
   285  	g.Add(2)
   286  	g.Add(3)
   287  	g.Connect(BasicEdge(3, 2))
   288  	g.Connect(BasicEdge(2, 1))
   289  
   290  	var visits []Vertex
   291  	var lock sync.Mutex
   292  	err := g.ReverseDepthFirstWalk([]Vertex{1}, func(v Vertex, d int) error {
   293  		lock.Lock()
   294  		defer lock.Unlock()
   295  		visits = append(visits, v)
   296  		g.Remove(v)
   297  		return nil
   298  	})
   299  	if err != nil {
   300  		t.Fatalf("err: %s", err)
   301  	}
   302  
   303  	expected := []Vertex{1, 2, 3}
   304  	if !reflect.DeepEqual(visits, expected) {
   305  		t.Fatalf("expected: %#v, got: %#v", expected, visits)
   306  	}
   307  }
   308  
   309  const testGraphTransReductionStr = `
   310  1
   311    2
   312  2
   313    3
   314  3
   315  `
   316  
   317  const testGraphTransReductionMoreStr = `
   318  1
   319    2
   320  2
   321    3
   322  3
   323    4
   324  4
   325  `