github.com/seeker-insurance/kit@v0.0.13/tsv/tsv_test.go (about)

     1  package tsv
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"io/ioutil"
     7  	"log"
     8  	"net/http"
     9  	"os"
    10  	"reflect"
    11  	"sort"
    12  	"strings"
    13  	"testing"
    14  )
    15  
    16  const (
    17  	johnFirst               = `john`
    18  	johnLast                = `doe`
    19  	johnAge                 = `22`
    20  	janeFirst               = `jane`
    21  	janeLast                = `doe`
    22  	janeAge                 = `58`
    23  	last, lng               = 22.3, -22.4
    24  	firstLabel              = "first"
    25  	lastLabel               = "last"
    26  	ageLabel                = "age"
    27  	testFileName            = "test.tsv"
    28  	localURL                = `http://localhost:3000/test.tsv`
    29  	ownerAllUserReadExecute = os.FileMode(0755)
    30  )
    31  
    32  var (
    33  	wd, _        = os.Getwd()
    34  	testFilePath = wd + "/" + testFileName
    35  	testLabels   = []string{firstLabel, lastLabel, ageLabel}
    36  	johnDoe      = []string{johnFirst, johnLast, johnAge}
    37  	janeDoe      = []string{janeFirst, janeLast, janeAge}
    38  	testTSVBody  = strings.Join([]string{
    39  		strings.Join(testLabels, "\t"),
    40  		strings.Join(johnDoe, "\t"),
    41  		strings.Join(janeDoe, "\t"),
    42  	},
    43  		"\n",
    44  	)
    45  
    46  	johnRecord = Record{
    47  		firstLabel: johnFirst,
    48  		lastLabel:  johnLast,
    49  		ageLabel:   johnAge,
    50  	}
    51  	janeRecord = Record{
    52  		firstLabel: janeFirst,
    53  		lastLabel:  janeLast,
    54  		ageLabel:   janeAge,
    55  	}
    56  )
    57  
    58  func testTSV(args ...string) string {
    59  	return strings.Join(args, "\t")
    60  }
    61  
    62  func serveFromMockTSVServer() http.Handler {
    63  	fs := http.FileServer(http.Dir(""))
    64  	http.Handle("/", fs)
    65  	log.Println("serving...")
    66  	go func() {
    67  		err := http.ListenAndServe(":3000", nil)
    68  		if err != nil {
    69  			log.Println("serving failed")
    70  		}
    71  	}()
    72  	return fs
    73  }
    74  
    75  func createTestFile() error {
    76  	return ioutil.WriteFile("test.tsv", []byte(testTSVBody), ownerAllUserReadExecute)
    77  }
    78  
    79  func init() {
    80  	if err := createTestFile(); err != nil {
    81  		log.Fatalf("could not create test file")
    82  	}
    83  	serveFromMockTSVServer()
    84  
    85  }
    86  
    87  func TestRecord_Float64(t *testing.T) {
    88  	type args struct {
    89  		key string
    90  	}
    91  	tests := []struct {
    92  		name    string
    93  		record  Record
    94  		args    args
    95  		want    float64
    96  		wantErr bool
    97  	}{
    98  		{
    99  			name:   "ok",
   100  			record: Record{"latitude": "-22.34"},
   101  			args:   args{"latitude"},
   102  			want:   -22.34,
   103  		}, {
   104  			name:    "key dne",
   105  			record:  Record{},
   106  			args:    args{"latitude"},
   107  			wantErr: true,
   108  		}, {
   109  			name:    "key bad float",
   110  			record:  Record{"latitude": "aaddmm"},
   111  			args:    args{"latitude"},
   112  			wantErr: true,
   113  		},
   114  	}
   115  	for _, tt := range tests {
   116  		t.Run(tt.name, func(t *testing.T) {
   117  			got, err := tt.record.Float64(tt.args.key)
   118  			if (err != nil) != tt.wantErr {
   119  				t.Errorf("Record.Float64() error = %v, wantErr %v", err, tt.wantErr)
   120  				return
   121  			}
   122  			if got != tt.want {
   123  				t.Errorf("Record.Float64() = %v, want %v", got, tt.want)
   124  			}
   125  		})
   126  	}
   127  }
   128  
   129  func TestParseLine(t *testing.T) {
   130  	type args struct {
   131  		line   string
   132  		labels []string
   133  	}
   134  	tests := []struct {
   135  		name string
   136  		args args
   137  		want Record
   138  		ok   bool
   139  	}{
   140  		{
   141  			name: "ok",
   142  			args: args{line: testTSV(johnDoe...), labels: testLabels},
   143  			want: Record{"first": johnFirst, "last": johnLast, "age": johnAge},
   144  			ok:   true,
   145  		}, {
   146  			name: "wrong length",
   147  			args: args{line: testTSV(`"hello"`, `"my"`, `"name"`, `"is"`), labels: testLabels},
   148  			want: nil,
   149  			ok:   false,
   150  		},
   151  	}
   152  	for _, tt := range tests {
   153  		t.Run(tt.name, func(t *testing.T) {
   154  			got, ok := parseLine(tt.args.line, tt.args.labels)
   155  			if !reflect.DeepEqual(got, tt.want) {
   156  				t.Errorf("ParseLine() got = %v, want %v", got, tt.want)
   157  			}
   158  			if ok != tt.ok {
   159  				t.Errorf("ParseLine() ok = %v, want %v", ok, tt.ok)
   160  			}
   161  			recover()
   162  		})
   163  	}
   164  }
   165  
   166  func Test_asReadCloser(t *testing.T) {
   167  	type args struct {
   168  		s string
   169  	}
   170  	wd, _ := os.Getwd()
   171  
   172  	tests := []struct {
   173  		name       string
   174  		args       args
   175  		wantString string
   176  		wantErr    bool
   177  	}{
   178  		{
   179  			name:       "good url",
   180  			args:       args{localURL},
   181  			wantString: testTSVBody,
   182  		}, {
   183  			name:    "does not exist",
   184  			args:    args{"thisseemslike.agoodurl.com/right.tsv"},
   185  			wantErr: true,
   186  		},
   187  		{
   188  			name:       "good file",
   189  			wantString: testTSVBody,
   190  			args:       args{wd + "/" + testFileName},
   191  		},
   192  		{
   193  			name:    "bad file",
   194  			args:    args{"thisfiledoesnotexist.tsv"},
   195  			wantErr: true,
   196  		},
   197  	}
   198  	for _, tt := range tests {
   199  		t.Run(tt.name, func(t *testing.T) {
   200  			gotReadCloser, err := asReadCloser(tt.args.s)
   201  			if (err != nil) != tt.wantErr {
   202  				t.Errorf("asReadCloser() error = %v, wantErr %v", err, tt.wantErr)
   203  				return
   204  			} else if err != nil {
   205  				return
   206  			}
   207  			var got bytes.Buffer
   208  			io.Copy(&got, gotReadCloser)
   209  			if !reflect.DeepEqual(got.String(), tt.wantString) {
   210  				t.Errorf("asReadCLoser(): got %v, want %v", got.String(), tt.wantString)
   211  			}
   212  
   213  		})
   214  
   215  	}
   216  }
   217  
   218  func Test_FromPath(t *testing.T) {
   219  	want := []Record{johnRecord, janeRecord}
   220  	type args struct {
   221  		path string
   222  	}
   223  	tests := []struct {
   224  		name        string
   225  		args        args
   226  		wantRecords []Record
   227  		wantErr     bool
   228  	}{
   229  		{
   230  			name:        "ok website",
   231  			args:        args{localURL},
   232  			wantRecords: want,
   233  		}, {
   234  			name:        "ok local file",
   235  			args:        args{testFileName},
   236  			wantRecords: want,
   237  		}, {
   238  			name:    "bad path",
   239  			args:    args{"badfile.asdasd"},
   240  			wantErr: true,
   241  		},
   242  	}
   243  	for _, tt := range tests {
   244  		t.Run(tt.name, func(t *testing.T) {
   245  			gotRecords, err := FromPath(tt.args.path)
   246  			if (err != nil) != tt.wantErr {
   247  				t.Errorf("parseFromPath() error = %v, wantErr %v", err, tt.wantErr)
   248  				return
   249  			}
   250  			if !reflect.DeepEqual(gotRecords, tt.wantRecords) {
   251  				t.Errorf("parseFromPath() = %v, want %v", gotRecords, tt.wantRecords)
   252  			}
   253  		})
   254  	}
   255  }
   256  
   257  func TestParse(t *testing.T) {
   258  	type args struct {
   259  		reader io.Reader
   260  	}
   261  	mismatched := bytes.NewBufferString("first\tlast\tage\njohn\tdoe\t22\njane\tdoe\n")
   262  	tests := []struct {
   263  		name        string
   264  		args        args
   265  		wantRecords []Record
   266  		wantErr     bool
   267  	}{
   268  		{
   269  			name:        "ok",
   270  			args:        args{reader: bytes.NewBufferString(testTSVBody)},
   271  			wantRecords: []Record{johnRecord, janeRecord},
   272  		}, {
   273  			name:    "mistmatched records",
   274  			args:    args{reader: mismatched},
   275  			wantErr: true,
   276  		},
   277  	}
   278  	for _, tt := range tests {
   279  		t.Run(tt.name, func(t *testing.T) {
   280  			gotRecords, err := Parse(tt.args.reader)
   281  			if (err != nil) != tt.wantErr {
   282  				t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
   283  				return
   284  			}
   285  			if !reflect.DeepEqual(gotRecords, tt.wantRecords) {
   286  				t.Errorf("Parse() = %v, want %v", gotRecords, tt.wantRecords)
   287  			}
   288  		})
   289  	}
   290  }
   291  
   292  type byFirstName []Record
   293  
   294  func (r byFirstName) Less(i, j int) bool {
   295  	fI, _ := r[i]["first"]
   296  	fJ, _ := r[j]["first"]
   297  	return fI < fJ
   298  }
   299  
   300  func (r byFirstName) Len() int {
   301  	return len(r)
   302  }
   303  
   304  func (r byFirstName) Swap(i, j int) {
   305  	r[i], r[j] = r[j], r[i]
   306  }
   307  
   308  func chanToSlice(ch <-chan Record) []Record {
   309  	var records []Record
   310  	for r := range ch {
   311  		records = append(records, r)
   312  	}
   313  	return records
   314  }
   315  
   316  func TestStreamFromPaths(t *testing.T) {
   317  	type args struct {
   318  		out   chan Record
   319  		paths []string
   320  	}
   321  	tests := []struct {
   322  		name    string
   323  		args    args
   324  		want    []Record
   325  		wantErr bool
   326  	}{
   327  		{
   328  			name: "ok - one path",
   329  			args: args{paths: []string{testFileName}, out: make(chan Record)},
   330  			want: []Record{johnRecord, janeRecord},
   331  		}, {
   332  			name: "ok - two paths",
   333  			args: args{paths: []string{testFileName, localURL}, out: make(chan Record, 2)},
   334  			want: []Record{johnRecord, johnRecord, janeRecord, janeRecord},
   335  		}, {
   336  			name:    "err - bad filepath",
   337  			args:    args{paths: []string{"somebadfilename"}, out: make(chan Record)},
   338  			wantErr: true,
   339  		},
   340  	}
   341  	for _, tt := range tests {
   342  		t.Run(tt.name, func(t *testing.T) {
   343  			if err := StreamFromPaths(tt.args.out, tt.args.paths...); (err != nil) != tt.wantErr {
   344  				t.Errorf("StreamFromPaths() error = %v, wantErr %v", err, tt.wantErr)
   345  			}
   346  			got := chanToSlice(tt.args.out)
   347  			sort.Sort(byFirstName(got))
   348  			sort.Sort(byFirstName(tt.want))
   349  			if !reflect.DeepEqual(got, tt.want) {
   350  				t.Errorf("StreamFromPaths(): \n got %v: \n want %v", got, tt.want)
   351  			}
   352  
   353  		})
   354  	}
   355  }
   356  
   357  func Test_labels_ParseLine(t *testing.T) {
   358  	type args struct {
   359  		line string
   360  	}
   361  	tests := []struct {
   362  		name  string
   363  		l     labels
   364  		args  args
   365  		want  Record
   366  		want1 bool
   367  	}{
   368  	// TODO: Add test cases.
   369  	}
   370  	for _, tt := range tests {
   371  		t.Run(tt.name, func(t *testing.T) {
   372  			got, got1 := tt.l.ParseLine(tt.args.line)
   373  			if !reflect.DeepEqual(got, tt.want) {
   374  				t.Errorf("labels.ParseLine() got = %v, want %v", got, tt.want)
   375  			}
   376  			if got1 != tt.want1 {
   377  				t.Errorf("labels.ParseLine() got1 = %v, want %v", got1, tt.want1)
   378  			}
   379  		})
   380  	}
   381  }
   382  
   383  func TestFromPath(t *testing.T) {
   384  	type args struct {
   385  		path string
   386  	}
   387  	tests := []struct {
   388  		name        string
   389  		args        args
   390  		wantRecords []Record
   391  		wantErr     bool
   392  	}{
   393  	// TODO: Add test cases.
   394  	}
   395  	for _, tt := range tests {
   396  		t.Run(tt.name, func(t *testing.T) {
   397  			gotRecords, err := FromPath(tt.args.path)
   398  			if (err != nil) != tt.wantErr {
   399  				t.Errorf("FromPath() error = %v, wantErr %v", err, tt.wantErr)
   400  				return
   401  			}
   402  			if !reflect.DeepEqual(gotRecords, tt.wantRecords) {
   403  				t.Errorf("FromPath() = %v, want %v", gotRecords, tt.wantRecords)
   404  			}
   405  		})
   406  	}
   407  }
   408  
   409  func TestStreamFromBindataPaths(t *testing.T) {
   410  	type args struct {
   411  		out   chan Record
   412  		paths []string
   413  	}
   414  	tests := []struct {
   415  		name    string
   416  		args    args
   417  		wantErr bool
   418  	}{
   419  	// TODO: Add test cases.
   420  	}
   421  	for _, tt := range tests {
   422  		t.Run(tt.name, func(t *testing.T) {
   423  			if err := StreamFromBindataPaths(tt.args.out, tt.args.paths...); (err != nil) != tt.wantErr {
   424  				t.Errorf("StreamFromBindataPaths() error = %v, wantErr %v", err, tt.wantErr)
   425  			}
   426  		})
   427  	}
   428  }
   429  
   430  func Test_asBinReadCloser(t *testing.T) {
   431  }
   432  
   433  func Test_parseStream(t *testing.T) {
   434  }
   435  
   436  func Test_parseStreams(t *testing.T) {
   437  }