github.com/hzck/speedroute@v0.0.0-20201115191102-403b7d0e443f/algorithm/algorithm_test.go (about)

     1  package algorithm
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"math/rand"
     7  	"os"
     8  	"testing"
     9  
    10  	m "github.com/hzck/speedroute/model"
    11  	"github.com/hzck/speedroute/parser"
    12  )
    13  
    14  // TestAllFiles goes through tests/ folder and tries to route a path, verifying towards files
    15  // in validations/ folder. Folder structure is the same in both tests/ and validations/ to
    16  // know which validation belongs to which test case.
    17  func TestAllFiles(t *testing.T) {
    18  	for _, testPath := range getDirFileNames(t, "tests/") {
    19  		graph, err := parser.CreateGraphFromFile(testPath)
    20  		if err != nil {
    21  			failAndPrint(t, err.Error())
    22  		}
    23  		validation, err := os.Open("validations/" + testPath[6:])
    24  		defer func() {
    25  			if closeErr := validation.Close(); closeErr != nil && err == nil {
    26  				failAndPrint(t, closeErr.Error())
    27  			}
    28  		}()
    29  		if err != nil {
    30  			assertFailingPath(t, graph, testPath)
    31  			continue
    32  		}
    33  		var path []string
    34  		scanner := bufio.NewScanner(validation)
    35  		for scanner.Scan() {
    36  			path = append(path, scanner.Text())
    37  		}
    38  		assertCorrectPath(t, path, Route(graph), testPath)
    39  	}
    40  }
    41  
    42  func getDirFileNames(t *testing.T, dirName string) []string {
    43  	var fileNames []string
    44  	dir, err := os.Open(dirName)
    45  	defer func() {
    46  		if closeErr := dir.Close(); closeErr != nil && err == nil {
    47  			failAndPrint(t, "Can't close dir: "+closeErr.Error())
    48  		}
    49  	}()
    50  	if err != nil {
    51  		failAndPrint(t, "Can't open dir: "+err.Error())
    52  		return nil
    53  	}
    54  	files, _ := dir.Readdir(-1)
    55  	for _, file := range files {
    56  		if file.IsDir() {
    57  			fileNames = append(fileNames, getDirFileNames(t, dirName+file.Name()+"/")...)
    58  			continue
    59  		}
    60  		fileNames = append(fileNames, dirName+file.Name())
    61  	}
    62  	return fileNames
    63  }
    64  
    65  func assertFailingPath(t *testing.T, graph *m.Graph, testPath string) {
    66  	if Route(graph) != nil {
    67  		failAndPrint(t, "assertFailingPath: "+testPath)
    68  	}
    69  }
    70  
    71  func assertCorrectPath(t *testing.T, nodes []string, path []*m.Edge, testPath string) {
    72  	if len(path) != len(nodes)-1 {
    73  		failAndPrint(t, "assertCorrectPath - len: "+testPath)
    74  	}
    75  	for i, edge := range path {
    76  		if edge.From().ID() != nodes[i] || edge.To().ID() != nodes[i+1] {
    77  			failAndPrint(t, "assertCorrectPath - correct "+nodes[i]+"->"+nodes[i+1]+", is "+edge.From().ID()+"->"+edge.To().ID()+": "+testPath)
    78  		}
    79  	}
    80  }
    81  
    82  func failAndPrint(t *testing.T, testPath string) {
    83  	t.Fail()
    84  	fmt.Println("Failing " + testPath)
    85  }
    86  
    87  // TestBenchmarkGraph verifies that the benchmarking randomized graph works.
    88  func TestBenchmarkGraph(t *testing.T) {
    89  	size := 4
    90  	graph := createBenchmarkGraph(size)
    91  	path := Route(graph)
    92  	if len(path) != size*2 {
    93  		t.Fail()
    94  	}
    95  }
    96  
    97  // BenchmarkAlgorithm consists of an int of the magnitude the graph should be benchmarked against.
    98  func BenchmarkAlgorithm(b *testing.B) {
    99  	graph := createBenchmarkGraph(30)
   100  	b.ResetTimer()
   101  	Route(graph)
   102  }
   103  
   104  // createBenchmarkGraph creates a graph from an int parameter specifying the magnitude of the graph.
   105  // Nodes: n²+n+1. Edges: n³+n². Possible paths: (can't remember).
   106  func createBenchmarkGraph(size int) *m.Graph {
   107  	transitionNode := m.CreateNode("tempId", false)
   108  	startNode := transitionNode
   109  	for i := 0; i < size; i++ {
   110  		var nodes []*m.Node
   111  		tempNode := m.CreateNode("tempId", false)
   112  		for k := 0; k < size; k++ {
   113  			newNode := m.CreateNode("tempId", false)
   114  			nodes = append(nodes, newNode)
   115  			createWeightedEdge(transitionNode, newNode, rand.Intn(10000)+1)
   116  			createWeightedEdge(newNode, tempNode, rand.Intn(10000)+1)
   117  		}
   118  		transitionNode = tempNode
   119  		for _, a := range nodes {
   120  			for _, b := range nodes {
   121  				if a != b {
   122  					createWeightedEdge(a, b, rand.Intn(10000)+1)
   123  				}
   124  			}
   125  		}
   126  	}
   127  	return m.CreateGraph(startNode, transitionNode)
   128  }
   129  
   130  func createWeightedEdge(from, to *m.Node, time int) {
   131  	edge := m.CreateEdge(from, to)
   132  	edge.AddWeight(m.CreateWeight(time))
   133  }