github.com/vlifesystems/rulehunter@v0.0.0-20180501090014-673078aa4a83/cmd/serve_test.go (about)

     1  package cmd
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"os"
     8  	"path/filepath"
     9  	"reflect"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/phayes/freeport"
    15  	"github.com/vlifesystems/rulehunter/internal"
    16  	"github.com/vlifesystems/rulehunter/internal/testhelpers"
    17  	"github.com/vlifesystems/rulehunter/quitter"
    18  )
    19  
    20  func TestRunServe(t *testing.T) {
    21  	wantEntries := []testhelpers.Entry{
    22  		{Level: testhelpers.Error,
    23  			Msg: "Can't load experiment: 0debt_broken.yaml, yaml: line 5: did not find expected key"},
    24  		{Level: testhelpers.Info,
    25  			Msg: "Processing experiment: debt.json, mode: train"},
    26  		{Level: testhelpers.Info,
    27  			Msg: "Successfully processed experiment: debt.json, mode: train"},
    28  		{Level: testhelpers.Info,
    29  			Msg: "Processing experiment: debt.yaml, mode: train"},
    30  		{Level: testhelpers.Info,
    31  			Msg: "Successfully processed experiment: debt.yaml, mode: train"},
    32  		{Level: testhelpers.Info,
    33  			Msg: "Processing experiment: debt2.json, mode: train"},
    34  		{Level: testhelpers.Info,
    35  			Msg: "Successfully processed experiment: debt2.json, mode: train"},
    36  	}
    37  	wantReportFiles := []string{
    38  		// "debt2.json"
    39  		internal.MakeBuildFilename(
    40  			"train",
    41  			"",
    42  			"What is most likely to indicate success (2)",
    43  		),
    44  		// "debt.yaml"
    45  		internal.MakeBuildFilename(
    46  			"train",
    47  			"testing",
    48  			"What is most likely to indicate success",
    49  		),
    50  		// "debt.json"
    51  		internal.MakeBuildFilename(
    52  			"train",
    53  			"",
    54  			"What is most likely to indicate success",
    55  		),
    56  	}
    57  
    58  	cfgDir := testhelpers.BuildConfigDirs(t, false)
    59  	cfgFilename := filepath.Join(cfgDir, "config.yaml")
    60  	defer os.RemoveAll(cfgDir)
    61  	testhelpers.MustWriteConfig(t, cfgDir, 100)
    62  	l := testhelpers.NewLogger()
    63  	q := quitter.New()
    64  
    65  	go func() {
    66  		if err := runServe(l, q, cfgFilename); err != nil {
    67  			t.Errorf("runServe: %s", err)
    68  		}
    69  	}()
    70  
    71  	if !testing.Short() {
    72  		time.Sleep(2 * time.Second)
    73  	}
    74  
    75  	experimentFiles := []string{
    76  		"debt.json",
    77  		"debt.yaml",
    78  		"0debt_broken.yaml",
    79  		"debt2.json",
    80  		"debt.jso",
    81  	}
    82  	for _, f := range experimentFiles {
    83  		testhelpers.CopyFile(
    84  			t,
    85  			filepath.Join("fixtures", f),
    86  			filepath.Join(cfgDir, "experiments"),
    87  		)
    88  	}
    89  
    90  	hasQuit := false
    91  	tickerC := time.NewTicker(100 * time.Millisecond).C
    92  	timeoutC := time.NewTimer(20 * time.Second).C
    93  	for !hasQuit {
    94  		select {
    95  		case <-tickerC:
    96  			gotReportFiles := testhelpers.GetFilesInDir(
    97  				t,
    98  				filepath.Join(cfgDir, "build", "reports"),
    99  			)
   100  			if len(gotReportFiles) == 3 {
   101  				q.Quit()
   102  				hasQuit = true
   103  				break
   104  			}
   105  		case <-timeoutC:
   106  			t.Fatal("runServe hasn't stopped")
   107  		}
   108  	}
   109  
   110  	time.Sleep(4 * time.Second)
   111  
   112  	gotReportFiles := testhelpers.GetFilesInDir(
   113  		t,
   114  		filepath.Join(cfgDir, "build", "reports"),
   115  	)
   116  	if !reflect.DeepEqual(gotReportFiles, wantReportFiles) {
   117  		t.Errorf("GetFilesInDir - got: %v\n want: %v",
   118  			gotReportFiles, wantReportFiles)
   119  	}
   120  
   121  	gotEntries := l.GetEntries()
   122  	if err := doLogEntriesMatch(gotEntries, wantEntries); err != nil {
   123  		t.Errorf("GetEntries: %s", err)
   124  	}
   125  	// TODO: Test all files generated
   126  }
   127  
   128  func TestRunServe_http(t *testing.T) {
   129  	httpPort, err := freeport.GetFreePort()
   130  	if err != nil {
   131  		t.Fatalf("GetFreePort: %d", err)
   132  	}
   133  	wantEntries := []testhelpers.Entry{
   134  		{Level: testhelpers.Info,
   135  			Msg: fmt.Sprintf("Starting http server on port: %d", httpPort)},
   136  		{Level: testhelpers.Info,
   137  			Msg: fmt.Sprintf("Shutdown http server on port: %d", httpPort)},
   138  		{Level: testhelpers.Error,
   139  			Msg: "Can't load experiment: 0debt_broken.yaml, yaml: line 5: did not find expected key"},
   140  		{Level: testhelpers.Info,
   141  			Msg: "Processing experiment: debt.json, mode: train"},
   142  		{Level: testhelpers.Info,
   143  			Msg: "Successfully processed experiment: debt.json, mode: train"},
   144  		{Level: testhelpers.Info,
   145  			Msg: "Processing experiment: debt.yaml, mode: train"},
   146  		{Level: testhelpers.Info,
   147  			Msg: "Successfully processed experiment: debt.yaml, mode: train"},
   148  		{Level: testhelpers.Info,
   149  			Msg: "Processing experiment: debt2.json, mode: train"},
   150  		{Level: testhelpers.Info,
   151  			Msg: "Successfully processed experiment: debt2.json, mode: train"},
   152  	}
   153  
   154  	cfgDir := testhelpers.BuildConfigDirs(t, false)
   155  	cfgFilename := filepath.Join(cfgDir, "config.yaml")
   156  	defer os.RemoveAll(cfgDir)
   157  	testhelpers.MustWriteConfig(t, cfgDir, 100, httpPort)
   158  	l := testhelpers.NewLogger()
   159  	q := quitter.New()
   160  
   161  	go func() {
   162  		if err := runServe(l, q, cfgFilename); err != nil {
   163  			t.Errorf("runServe: %s", err)
   164  		}
   165  	}()
   166  
   167  	if !testing.Short() {
   168  		time.Sleep(2 * time.Second)
   169  	}
   170  
   171  	experimentFiles := []string{
   172  		"debt.json",
   173  		"debt.yaml",
   174  		"0debt_broken.yaml",
   175  		"debt2.json",
   176  		"debt.jso",
   177  	}
   178  	for _, f := range experimentFiles {
   179  		testhelpers.CopyFile(
   180  			t,
   181  			filepath.Join("fixtures", f),
   182  			filepath.Join(cfgDir, "experiments"),
   183  		)
   184  	}
   185  
   186  	wantText := "Rulehunter"
   187  	resp, err := http.Get(fmt.Sprintf("http://localhost:%d", httpPort))
   188  	if err != nil {
   189  		q.Quit()
   190  		t.Fatalf("http.Get: %s", err)
   191  	}
   192  	if resp.StatusCode != 200 {
   193  		q.Quit()
   194  		t.Fatalf("received non-200 response: %d", resp.StatusCode)
   195  	}
   196  	body, err := ioutil.ReadAll(resp.Body)
   197  	if err != nil {
   198  		q.Quit()
   199  		t.Fatal(err)
   200  	}
   201  	if !strings.Contains(string(body[:]), wantText) {
   202  		t.Errorf("web page doesn't contain: %s", wantText)
   203  	}
   204  
   205  	hasQuit := false
   206  	tickerC := time.NewTicker(100 * time.Millisecond).C
   207  	timeoutC := time.NewTimer(20 * time.Second).C
   208  	for !hasQuit {
   209  		select {
   210  		case <-tickerC:
   211  			gotReportFiles := testhelpers.GetFilesInDir(
   212  				t,
   213  				filepath.Join(cfgDir, "build", "reports"),
   214  			)
   215  			if len(gotReportFiles) == 3 {
   216  				q.Quit()
   217  				hasQuit = true
   218  				break
   219  			}
   220  		case <-timeoutC:
   221  			q.Quit()
   222  			t.Fatal("runServe hasn't stopped")
   223  		}
   224  	}
   225  
   226  	time.Sleep(4 * time.Second)
   227  
   228  	gotEntries := l.GetEntries()
   229  	if err := doLogEntriesMatch(gotEntries, wantEntries); err != nil {
   230  		t.Errorf("GetEntries: %s", err)
   231  	}
   232  	// TODO: Test all files generated
   233  }