github.com/rainforestapp/rainforest-cli@v2.12.0+incompatible/tabularvars_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"os"
     7  	"reflect"
     8  	"testing"
     9  
    10  	"log"
    11  
    12  	"strings"
    13  
    14  	"github.com/rainforestapp/rainforest-cli/rainforest"
    15  	"github.com/urfave/cli"
    16  )
    17  
    18  const (
    19  	fakeCSVPath = "./fake.csv"
    20  )
    21  
    22  func TestMin(t *testing.T) {
    23  	var testCases = []struct {
    24  		a        int
    25  		b        int
    26  		expected int
    27  	}{
    28  		{
    29  			a:        1,
    30  			b:        3,
    31  			expected: 1,
    32  		},
    33  		{
    34  			a:        100,
    35  			b:        23,
    36  			expected: 23,
    37  		},
    38  		{
    39  			a:        42,
    40  			b:        42,
    41  			expected: 42,
    42  		},
    43  	}
    44  
    45  	for _, testCase := range testCases {
    46  		res := min(testCase.a, testCase.b)
    47  
    48  		if res != testCase.expected {
    49  			t.Errorf("Incorrect value for min(%v, %v) = %v, expected: %v",
    50  				testCase.a, testCase.b, res, testCase.expected)
    51  		}
    52  	}
    53  }
    54  
    55  type fakePI struct {
    56  	getGenerators    func() ([]rainforest.Generator, error)
    57  	deleteGenerator  func(genID int) error
    58  	createTabularVar func(name, description string,
    59  		columns []string, singleUse bool) (*rainforest.Generator, error)
    60  	addGeneratorRowsFromTable func(targetGenerator *rainforest.Generator,
    61  		targetColumns []string, rowData [][]string) error
    62  }
    63  
    64  func (f fakePI) GetGenerators() ([]rainforest.Generator, error) {
    65  	if f.getGenerators != nil {
    66  		return f.getGenerators()
    67  	}
    68  	return nil, nil
    69  }
    70  
    71  func (f fakePI) DeleteGenerator(genID int) error {
    72  	if f.deleteGenerator != nil {
    73  		return f.deleteGenerator(genID)
    74  	}
    75  	return nil
    76  }
    77  
    78  func (f fakePI) CreateTabularVar(name, description string,
    79  	columns []string, singleUse bool) (*rainforest.Generator, error) {
    80  	if f.createTabularVar != nil {
    81  		return f.createTabularVar(name, description, columns, singleUse)
    82  	}
    83  	return &rainforest.Generator{}, nil
    84  }
    85  
    86  func (f fakePI) AddGeneratorRowsFromTable(targetGenerator *rainforest.Generator,
    87  	targetColumns []string, rowData [][]string) error {
    88  	if f.addGeneratorRowsFromTable != nil {
    89  		return f.addGeneratorRowsFromTable(targetGenerator, targetColumns, rowData)
    90  	}
    91  	return nil
    92  }
    93  
    94  func TestRowUploadWorker(t *testing.T) {
    95  	const testBatchesCount = 2
    96  	gen := &rainforest.Generator{ID: 123}
    97  	cols := []string{"test", "columns"}
    98  	inChan := make(chan [][]string, testBatchesCount)
    99  	firstBatch := [][]string{{"foo", "bar"}, {"baz", "wut"}}
   100  	inChan <- firstBatch
   101  	secondBatch := [][]string{{"qwe", "asd"}, {"zxc", "jkl"}}
   102  	inChan <- secondBatch
   103  	close(inChan)
   104  	errorsChan := make(chan error, testBatchesCount)
   105  	var callCount int
   106  	f := fakePI{
   107  		addGeneratorRowsFromTable: func(targetGenerator *rainforest.Generator,
   108  			targetColumns []string, rowData [][]string) error {
   109  			if !reflect.DeepEqual(targetGenerator, gen) {
   110  				t.Errorf("Incorrect value of targetGenerator passed. Got: %v, expected: %v", targetGenerator, gen)
   111  			}
   112  			if !reflect.DeepEqual(targetColumns, cols) {
   113  				t.Errorf("Incorrect value of targetColumns passed. Got: %v, expected: %v", targetColumns, cols)
   114  			}
   115  			if callCount == 0 && !reflect.DeepEqual(rowData, firstBatch) {
   116  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, firstBatch)
   117  			}
   118  			if callCount == 1 && !reflect.DeepEqual(rowData, secondBatch) {
   119  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, secondBatch)
   120  			}
   121  			callCount = callCount + 1
   122  			return nil
   123  		},
   124  	}
   125  	rowUploadWorker(f, gen, cols, inChan, errorsChan)
   126  	if callCount != testBatchesCount {
   127  		t.Errorf("Api called wrong number of times. Called: %v, expected: %v", callCount, testBatchesCount)
   128  	}
   129  	err := <-errorsChan
   130  	if err != nil {
   131  		t.Errorf("Unexpected error: %v", err.Error())
   132  	}
   133  	err = <-errorsChan
   134  	if err != nil {
   135  		t.Errorf("Unexpected error: %v", err.Error())
   136  	}
   137  }
   138  
   139  func TestRowUploadWorker_Error(t *testing.T) {
   140  	const testBatchesCount = 2
   141  	gen := &rainforest.Generator{ID: 123}
   142  	cols := []string{"test", "columns"}
   143  	inChan := make(chan [][]string, testBatchesCount)
   144  	firstBatch := [][]string{{"foo", "bar"}, {"baz", "wut"}}
   145  	inChan <- firstBatch
   146  	secondBatch := [][]string{{"qwe", "asd"}, {"zxc", "jkl"}}
   147  	inChan <- secondBatch
   148  	close(inChan)
   149  	errorsChan := make(chan error, testBatchesCount)
   150  	var callCount int
   151  	f := fakePI{
   152  		addGeneratorRowsFromTable: func(targetGenerator *rainforest.Generator,
   153  			targetColumns []string, rowData [][]string) error {
   154  			if !reflect.DeepEqual(targetGenerator, gen) {
   155  				t.Errorf("Incorrect value of targetGenerator passed. Got: %v, expected: %v", targetGenerator, gen)
   156  			}
   157  			if !reflect.DeepEqual(targetColumns, cols) {
   158  				t.Errorf("Incorrect value of targetColumns passed. Got: %v, expected: %v", targetColumns, cols)
   159  			}
   160  			if callCount == 0 && !reflect.DeepEqual(rowData, firstBatch) {
   161  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, firstBatch)
   162  			}
   163  			if callCount == 1 && !reflect.DeepEqual(rowData, secondBatch) {
   164  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, secondBatch)
   165  			}
   166  			callCount = callCount + 1
   167  			return errors.New("PICNIC!!1")
   168  		},
   169  	}
   170  	rowUploadWorker(f, gen, cols, inChan, errorsChan)
   171  	if callCount != testBatchesCount {
   172  		t.Errorf("Api called wrong number of times. Called: %v, expected: %v", callCount, testBatchesCount)
   173  	}
   174  	err := <-errorsChan
   175  	if err == nil {
   176  		t.Errorf("Expected error, instead got nil.")
   177  	}
   178  }
   179  
   180  func createValidFakeCSV(t *testing.T) {
   181  	f, err := os.Create(fakeCSVPath)
   182  	if err != nil {
   183  		t.Fatal("Couldn't create the test csv file.")
   184  	}
   185  	defer f.Close()
   186  
   187  	f.WriteString("test,columns\nfoo,bar\nbaz,wut\nqwe,asd\nzxc,jkl\n")
   188  }
   189  
   190  func deleteFakeCSV(t *testing.T) {
   191  	err := os.Remove(fakeCSVPath)
   192  	if err != nil {
   193  		t.Fatal("Couldn't remove the test csv file.")
   194  	}
   195  }
   196  
   197  func TestUploadTabularVar(t *testing.T) {
   198  	// Setup testing  stuff
   199  	createValidFakeCSV(t)
   200  	defer deleteFakeCSV(t)
   201  	tabularBatchSize = 2
   202  	variableName := "testVar"
   203  	variableOverwrite := false
   204  	variableSingleUse := false
   205  	// Data from csv
   206  	cols := []string{"test", "columns"}
   207  	firstBatch := [][]string{{"foo", "bar"}, {"baz", "wut"}}
   208  	secondBatch := [][]string{{"qwe", "asd"}, {"zxc", "jkl"}}
   209  	// Fake responses Data
   210  	fakeNewGen := rainforest.Generator{
   211  		ID:   123,
   212  		Name: variableName,
   213  		Columns: []rainforest.GeneratorColumn{
   214  			{
   215  				ID:   456,
   216  				Name: "test",
   217  			},
   218  			{
   219  				ID:   789,
   220  				Name: "columns",
   221  			},
   222  		},
   223  	}
   224  	callCount := make(map[string]int)
   225  	f := fakePI{
   226  		addGeneratorRowsFromTable: func(targetGenerator *rainforest.Generator,
   227  			targetColumns []string, rowData [][]string) error {
   228  			if !reflect.DeepEqual(targetGenerator, &fakeNewGen) {
   229  				t.Errorf("Incorrect value of targetGenerator passed. Got: %v, expected: %v", targetGenerator, fakeNewGen)
   230  			}
   231  			if !reflect.DeepEqual(targetColumns, cols) {
   232  				t.Errorf("Incorrect value of targetColumns passed. Got: %v, expected: %v", targetColumns, cols)
   233  			}
   234  			if callCount["addGeneratorRowsFromTable"] == 0 && !reflect.DeepEqual(rowData, firstBatch) {
   235  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, firstBatch)
   236  			}
   237  			if callCount["addGeneratorRowsFromTable"] == 1 && !reflect.DeepEqual(rowData, secondBatch) {
   238  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, secondBatch)
   239  			}
   240  			callCount["addGeneratorRowsFromTable"] = callCount["addGeneratorRowsFromTable"] + 1
   241  			return nil
   242  		},
   243  		getGenerators: func() ([]rainforest.Generator, error) {
   244  			callCount["getGenerators"] = callCount["getGenerators"] + 1
   245  			return []rainforest.Generator{
   246  				{
   247  					ID:   42,
   248  					Name: "Kappa",
   249  				},
   250  				{
   251  					ID:   1337,
   252  					Name: "EleGiggle",
   253  				},
   254  			}, nil
   255  		},
   256  		deleteGenerator: func(genID int) error {
   257  			if genID != fakeNewGen.ID {
   258  				t.Errorf("Incorrect value of genID passed to delete. Got: %v, expected: %v", genID, fakeNewGen.ID)
   259  			}
   260  			callCount["deleteGenerator"] = callCount["deleteGenerator"] + 1
   261  			return nil
   262  		},
   263  		createTabularVar: func(name, description string, columns []string,
   264  			singleUse bool) (*rainforest.Generator, error) {
   265  			if variableName != name {
   266  				t.Errorf("Incorrect value of name passed to newTabVar. Got: %v, expected: %v", name, variableName)
   267  			}
   268  			if !reflect.DeepEqual(columns, cols) {
   269  				t.Errorf("Incorrect value of columns passed to newTabVar. Got: %v, expected: %v", columns, cols)
   270  			}
   271  			if variableSingleUse != singleUse {
   272  				t.Errorf("Incorrect value of singleUse passed to newTabVar. Got: %v, expected: %v", singleUse, variableSingleUse)
   273  			}
   274  			callCount["createTabularVar"] = callCount["createTabularVar"] + 1
   275  			return &fakeNewGen, nil
   276  		},
   277  	}
   278  
   279  	// Capture output
   280  	var outBuffer bytes.Buffer
   281  	log.SetOutput(&outBuffer)
   282  	defer log.SetOutput(os.Stdout)
   283  
   284  	err := uploadTabularVar(f, fakeCSVPath, variableName, variableOverwrite, variableSingleUse)
   285  	if err != nil {
   286  		t.Errorf("Unexpected error: %v", err.Error())
   287  	}
   288  	if expected := 1; callCount["getGenerators"] != expected {
   289  		t.Errorf("api.getGenerators called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   290  	}
   291  	if expected := 0; callCount["deleteGenerator"] != expected {
   292  		t.Errorf("api.deleteGenerator called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   293  	}
   294  	if expected := 1; callCount["createTabularVar"] != expected {
   295  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   296  	}
   297  	if expected := 2; callCount["addGeneratorRowsFromTable"] != expected {
   298  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   299  	}
   300  
   301  	if !strings.Contains(outBuffer.String(), "uploaded") {
   302  		t.Errorf("Expected progress updates logged out (containing 'uploaded'), got %v", outBuffer.String())
   303  	}
   304  }
   305  
   306  func TestUploadTabularVar_Exists_NoOverwrite(t *testing.T) {
   307  	// Setup testing  stuff
   308  	createValidFakeCSV(t)
   309  	defer deleteFakeCSV(t)
   310  	tabularBatchSize = 2
   311  	variableName := "testVar"
   312  	variableOverwrite := false
   313  	variableSingleUse := false
   314  	// Data from csv
   315  	cols := []string{"test", "columns"}
   316  	firstBatch := [][]string{{"foo", "bar"}, {"baz", "wut"}}
   317  	secondBatch := [][]string{{"qwe", "asd"}, {"zxc", "jkl"}}
   318  	// Fake responses Data
   319  	fakeNewGen := rainforest.Generator{
   320  		ID:   123,
   321  		Name: variableName,
   322  		Columns: []rainforest.GeneratorColumn{
   323  			{
   324  				ID:   456,
   325  				Name: "test",
   326  			},
   327  			{
   328  				ID:   789,
   329  				Name: "columns",
   330  			},
   331  		},
   332  	}
   333  	callCount := make(map[string]int)
   334  	f := fakePI{
   335  		addGeneratorRowsFromTable: func(targetGenerator *rainforest.Generator,
   336  			targetColumns []string, rowData [][]string) error {
   337  			if !reflect.DeepEqual(targetGenerator, &fakeNewGen) {
   338  				t.Errorf("Incorrect value of targetGenerator passed. Got: %v, expected: %v", targetGenerator, fakeNewGen)
   339  			}
   340  			if !reflect.DeepEqual(targetColumns, cols) {
   341  				t.Errorf("Incorrect value of targetColumns passed. Got: %v, expected: %v", targetColumns, cols)
   342  			}
   343  			if callCount["addGeneratorRowsFromTable"] == 0 && !reflect.DeepEqual(rowData, firstBatch) {
   344  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, firstBatch)
   345  			}
   346  			if callCount["addGeneratorRowsFromTable"] == 1 && !reflect.DeepEqual(rowData, secondBatch) {
   347  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, secondBatch)
   348  			}
   349  			callCount["addGeneratorRowsFromTable"] = callCount["addGeneratorRowsFromTable"] + 1
   350  			return nil
   351  		},
   352  		getGenerators: func() ([]rainforest.Generator, error) {
   353  			callCount["getGenerators"] = callCount["getGenerators"] + 1
   354  			return []rainforest.Generator{
   355  				{
   356  					ID:   42,
   357  					Name: "Kappa",
   358  				},
   359  				{
   360  					ID:   1337,
   361  					Name: "EleGiggle",
   362  				},
   363  				fakeNewGen,
   364  			}, nil
   365  		},
   366  		deleteGenerator: func(genID int) error {
   367  			if genID != fakeNewGen.ID {
   368  				t.Errorf("Incorrect value of genID passed to delete. Got: %v, expected: %v", genID, fakeNewGen.ID)
   369  			}
   370  			callCount["deleteGenerator"] = callCount["deleteGenerator"] + 1
   371  			return nil
   372  		},
   373  		createTabularVar: func(name, description string, columns []string,
   374  			singleUse bool) (*rainforest.Generator, error) {
   375  			if variableName != name {
   376  				t.Errorf("Incorrect value of name passed to newTabVar. Got: %v, expected: %v", name, variableName)
   377  			}
   378  			if !reflect.DeepEqual(columns, cols) {
   379  				t.Errorf("Incorrect value of columns passed to newTabVar. Got: %v, expected: %v", columns, cols)
   380  			}
   381  			if variableSingleUse != singleUse {
   382  				t.Errorf("Incorrect value of singleUse passed to newTabVar. Got: %v, expected: %v", singleUse, variableSingleUse)
   383  			}
   384  			callCount["createTabularVar"] = callCount["createTabularVar"] + 1
   385  			return &fakeNewGen, nil
   386  		},
   387  	}
   388  	err := uploadTabularVar(f, fakeCSVPath, variableName, variableOverwrite, variableSingleUse)
   389  	if err == nil {
   390  		t.Errorf("Expected error, got nil")
   391  	}
   392  	if expected := 1; callCount["getGenerators"] != expected {
   393  		t.Errorf("api.getGenerators called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   394  	}
   395  	if expected := 0; callCount["deleteGenerator"] != expected {
   396  		t.Errorf("api.deleteGenerator called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   397  	}
   398  	if expected := 0; callCount["createTabularVar"] != expected {
   399  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   400  	}
   401  	if expected := 0; callCount["addGeneratorRowsFromTable"] != expected {
   402  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   403  	}
   404  }
   405  
   406  func TestUploadTabularVar_Exists_Overwrite(t *testing.T) {
   407  	// Setup testing  stuff
   408  	createValidFakeCSV(t)
   409  	defer deleteFakeCSV(t)
   410  	tabularBatchSize = 2
   411  	variableName := "testVar"
   412  	variableOverwrite := true
   413  	variableSingleUse := false
   414  	// Data from csv
   415  	cols := []string{"test", "columns"}
   416  	firstBatch := [][]string{{"foo", "bar"}, {"baz", "wut"}}
   417  	secondBatch := [][]string{{"qwe", "asd"}, {"zxc", "jkl"}}
   418  	// Fake responses Data
   419  	fakeNewGen := rainforest.Generator{
   420  		ID:   123,
   421  		Name: variableName,
   422  		Columns: []rainforest.GeneratorColumn{
   423  			{
   424  				ID:   456,
   425  				Name: "test",
   426  			},
   427  			{
   428  				ID:   789,
   429  				Name: "columns",
   430  			},
   431  		},
   432  	}
   433  	callCount := make(map[string]int)
   434  	f := fakePI{
   435  		addGeneratorRowsFromTable: func(targetGenerator *rainforest.Generator,
   436  			targetColumns []string, rowData [][]string) error {
   437  			if !reflect.DeepEqual(targetGenerator, &fakeNewGen) {
   438  				t.Errorf("Incorrect value of targetGenerator passed. Got: %v, expected: %v", targetGenerator, fakeNewGen)
   439  			}
   440  			if !reflect.DeepEqual(targetColumns, cols) {
   441  				t.Errorf("Incorrect value of targetColumns passed. Got: %v, expected: %v", targetColumns, cols)
   442  			}
   443  			if callCount["addGeneratorRowsFromTable"] == 0 && !reflect.DeepEqual(rowData, firstBatch) {
   444  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, firstBatch)
   445  			}
   446  			if callCount["addGeneratorRowsFromTable"] == 1 && !reflect.DeepEqual(rowData, secondBatch) {
   447  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, secondBatch)
   448  			}
   449  			callCount["addGeneratorRowsFromTable"] = callCount["addGeneratorRowsFromTable"] + 1
   450  			return nil
   451  		},
   452  		getGenerators: func() ([]rainforest.Generator, error) {
   453  			callCount["getGenerators"] = callCount["getGenerators"] + 1
   454  			return []rainforest.Generator{
   455  				{
   456  					ID:   42,
   457  					Name: "Kappa",
   458  				},
   459  				{
   460  					ID:   1337,
   461  					Name: "EleGiggle",
   462  				},
   463  				fakeNewGen,
   464  			}, nil
   465  		},
   466  		deleteGenerator: func(genID int) error {
   467  			if genID != fakeNewGen.ID {
   468  				t.Errorf("Incorrect value of genID passed to delete. Got: %v, expected: %v", genID, fakeNewGen.ID)
   469  			}
   470  			callCount["deleteGenerator"] = callCount["deleteGenerator"] + 1
   471  			return nil
   472  		},
   473  		createTabularVar: func(name, description string, columns []string,
   474  			singleUse bool) (*rainforest.Generator, error) {
   475  			if variableName != name {
   476  				t.Errorf("Incorrect value of name passed to newTabVar. Got: %v, expected: %v", name, variableName)
   477  			}
   478  			if !reflect.DeepEqual(columns, cols) {
   479  				t.Errorf("Incorrect value of columns passed to newTabVar. Got: %v, expected: %v", columns, cols)
   480  			}
   481  			if variableSingleUse != singleUse {
   482  				t.Errorf("Incorrect value of singleUse passed to newTabVar. Got: %v, expected: %v", singleUse, variableSingleUse)
   483  			}
   484  			callCount["createTabularVar"] = callCount["createTabularVar"] + 1
   485  			return &fakeNewGen, nil
   486  		},
   487  	}
   488  
   489  	// Capture output
   490  	var outBuffer bytes.Buffer
   491  	log.SetOutput(&outBuffer)
   492  	defer log.SetOutput(os.Stdout)
   493  
   494  	err := uploadTabularVar(f, fakeCSVPath, variableName, variableOverwrite, variableSingleUse)
   495  	if err != nil {
   496  		t.Errorf("Unexpected error: %v", err.Error())
   497  	}
   498  	if expected := 1; callCount["getGenerators"] != expected {
   499  		t.Errorf("api.getGenerators called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   500  	}
   501  	if expected := 1; callCount["deleteGenerator"] != expected {
   502  		t.Errorf("api.deleteGenerator called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   503  	}
   504  	if expected := 1; callCount["createTabularVar"] != expected {
   505  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   506  	}
   507  	if expected := 2; callCount["addGeneratorRowsFromTable"] != expected {
   508  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   509  	}
   510  
   511  	if !strings.Contains(outBuffer.String(), "uploaded") {
   512  		t.Errorf("Expected progress updates logged out (containing 'uploaded'), got %v", outBuffer.String())
   513  	}
   514  	if !strings.Contains(outBuffer.String(), "overwriting") {
   515  		t.Errorf("Expected information about overwriting variable, got %v", outBuffer.String())
   516  	}
   517  }
   518  
   519  func TestCSVUpload(t *testing.T) {
   520  	// Setup testing  stuff
   521  	createValidFakeCSV(t)
   522  	defer deleteFakeCSV(t)
   523  	tabularBatchSize = 2
   524  	variableName := "testVar"
   525  	variableOverwrite := true
   526  	variableSingleUse := false
   527  	// Data from csv
   528  	cols := []string{"test", "columns"}
   529  	firstBatch := [][]string{{"foo", "bar"}, {"baz", "wut"}}
   530  	secondBatch := [][]string{{"qwe", "asd"}, {"zxc", "jkl"}}
   531  	// Fake responses Data
   532  	fakeNewGen := rainforest.Generator{
   533  		ID:   123,
   534  		Name: variableName,
   535  		Columns: []rainforest.GeneratorColumn{
   536  			{
   537  				ID:   456,
   538  				Name: "test",
   539  			},
   540  			{
   541  				ID:   789,
   542  				Name: "columns",
   543  			},
   544  		},
   545  	}
   546  	callCount := make(map[string]int)
   547  	f := fakePI{
   548  		addGeneratorRowsFromTable: func(targetGenerator *rainforest.Generator,
   549  			targetColumns []string, rowData [][]string) error {
   550  			if !reflect.DeepEqual(targetGenerator, &fakeNewGen) {
   551  				t.Errorf("Incorrect value of targetGenerator passed. Got: %v, expected: %v", targetGenerator, fakeNewGen)
   552  			}
   553  			if !reflect.DeepEqual(targetColumns, cols) {
   554  				t.Errorf("Incorrect value of targetColumns passed. Got: %v, expected: %v", targetColumns, cols)
   555  			}
   556  			if callCount["addGeneratorRowsFromTable"] == 0 && !reflect.DeepEqual(rowData, firstBatch) {
   557  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, firstBatch)
   558  			}
   559  			if callCount["addGeneratorRowsFromTable"] == 1 && !reflect.DeepEqual(rowData, secondBatch) {
   560  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, secondBatch)
   561  			}
   562  			callCount["addGeneratorRowsFromTable"] = callCount["addGeneratorRowsFromTable"] + 1
   563  			return nil
   564  		},
   565  		getGenerators: func() ([]rainforest.Generator, error) {
   566  			callCount["getGenerators"] = callCount["getGenerators"] + 1
   567  			return []rainforest.Generator{
   568  				{
   569  					ID:   42,
   570  					Name: "Kappa",
   571  				},
   572  				{
   573  					ID:   1337,
   574  					Name: "EleGiggle",
   575  				},
   576  				fakeNewGen,
   577  			}, nil
   578  		},
   579  		deleteGenerator: func(genID int) error {
   580  			if genID != fakeNewGen.ID {
   581  				t.Errorf("Incorrect value of genID passed to delete. Got: %v, expected: %v", genID, fakeNewGen.ID)
   582  			}
   583  			callCount["deleteGenerator"] = callCount["deleteGenerator"] + 1
   584  			return nil
   585  		},
   586  		createTabularVar: func(name, description string, columns []string,
   587  			singleUse bool) (*rainforest.Generator, error) {
   588  			if variableName != name {
   589  				t.Errorf("Incorrect value of name passed to newTabVar. Got: %v, expected: %v", name, variableName)
   590  			}
   591  			if !reflect.DeepEqual(columns, cols) {
   592  				t.Errorf("Incorrect value of columns passed to newTabVar. Got: %v, expected: %v", columns, cols)
   593  			}
   594  			if variableSingleUse != singleUse {
   595  				t.Errorf("Incorrect value of singleUse passed to newTabVar. Got: %v, expected: %v", singleUse, variableSingleUse)
   596  			}
   597  			callCount["createTabularVar"] = callCount["createTabularVar"] + 1
   598  			return &fakeNewGen, nil
   599  		},
   600  	}
   601  
   602  	// Fake cli args
   603  	fakeContext := newFakeContext(map[string]interface{}{
   604  		"name":               variableName,
   605  		"overwrite-variable": variableOverwrite,
   606  		"single-use":         variableSingleUse,
   607  	}, cli.Args{fakeCSVPath})
   608  
   609  	// Capture output
   610  	var outBuffer bytes.Buffer
   611  	log.SetOutput(&outBuffer)
   612  	defer log.SetOutput(os.Stdout)
   613  
   614  	err := csvUpload(fakeContext, f)
   615  	if err != nil {
   616  		t.Errorf("Unexpected error: %v", err.Error())
   617  	}
   618  	if expected := 1; callCount["getGenerators"] != expected {
   619  		t.Errorf("api.getGenerators called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   620  	}
   621  	if expected := 1; callCount["deleteGenerator"] != expected {
   622  		t.Errorf("api.deleteGenerator called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   623  	}
   624  	if expected := 1; callCount["createTabularVar"] != expected {
   625  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   626  	}
   627  	if expected := 2; callCount["addGeneratorRowsFromTable"] != expected {
   628  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   629  	}
   630  
   631  	if !strings.Contains(outBuffer.String(), "uploaded") {
   632  		t.Errorf("Expected progress updates logged out (containing 'uploaded'), got %v", outBuffer.String())
   633  	}
   634  	if !strings.Contains(outBuffer.String(), "overwriting") {
   635  		t.Errorf("Expected information about overwriting variable, got %v", outBuffer.String())
   636  	}
   637  }
   638  
   639  func TestCSVUpload_MissingName(t *testing.T) {
   640  	// Setup testing  stuff
   641  	createValidFakeCSV(t)
   642  	defer deleteFakeCSV(t)
   643  	tabularBatchSize = 2
   644  	variableName := "testVar"
   645  	variableOverwrite := true
   646  	variableSingleUse := false
   647  	// Data from csv
   648  	cols := []string{"test", "columns"}
   649  	firstBatch := [][]string{{"foo", "bar"}, {"baz", "wut"}}
   650  	secondBatch := [][]string{{"qwe", "asd"}, {"zxc", "jkl"}}
   651  	// Fake responses Data
   652  	fakeNewGen := rainforest.Generator{
   653  		ID:   123,
   654  		Name: variableName,
   655  		Columns: []rainforest.GeneratorColumn{
   656  			{
   657  				ID:   456,
   658  				Name: "test",
   659  			},
   660  			{
   661  				ID:   789,
   662  				Name: "columns",
   663  			},
   664  		},
   665  	}
   666  	callCount := make(map[string]int)
   667  	f := fakePI{
   668  		addGeneratorRowsFromTable: func(targetGenerator *rainforest.Generator,
   669  			targetColumns []string, rowData [][]string) error {
   670  			if !reflect.DeepEqual(targetGenerator, &fakeNewGen) {
   671  				t.Errorf("Incorrect value of targetGenerator passed. Got: %v, expected: %v", targetGenerator, fakeNewGen)
   672  			}
   673  			if !reflect.DeepEqual(targetColumns, cols) {
   674  				t.Errorf("Incorrect value of targetColumns passed. Got: %v, expected: %v", targetColumns, cols)
   675  			}
   676  			if callCount["addGeneratorRowsFromTable"] == 0 && !reflect.DeepEqual(rowData, firstBatch) {
   677  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, firstBatch)
   678  			}
   679  			if callCount["addGeneratorRowsFromTable"] == 1 && !reflect.DeepEqual(rowData, secondBatch) {
   680  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, secondBatch)
   681  			}
   682  			callCount["addGeneratorRowsFromTable"] = callCount["addGeneratorRowsFromTable"] + 1
   683  			return nil
   684  		},
   685  		getGenerators: func() ([]rainforest.Generator, error) {
   686  			callCount["getGenerators"] = callCount["getGenerators"] + 1
   687  			return []rainforest.Generator{
   688  				{
   689  					ID:   42,
   690  					Name: "Kappa",
   691  				},
   692  				{
   693  					ID:   1337,
   694  					Name: "EleGiggle",
   695  				},
   696  				fakeNewGen,
   697  			}, nil
   698  		},
   699  		deleteGenerator: func(genID int) error {
   700  			if genID != fakeNewGen.ID {
   701  				t.Errorf("Incorrect value of genID passed to delete. Got: %v, expected: %v", genID, fakeNewGen.ID)
   702  			}
   703  			callCount["deleteGenerator"] = callCount["deleteGenerator"] + 1
   704  			return nil
   705  		},
   706  		createTabularVar: func(name, description string, columns []string,
   707  			singleUse bool) (*rainforest.Generator, error) {
   708  			if variableName != name {
   709  				t.Errorf("Incorrect value of name passed to newTabVar. Got: %v, expected: %v", name, variableName)
   710  			}
   711  			if !reflect.DeepEqual(columns, cols) {
   712  				t.Errorf("Incorrect value of columns passed to newTabVar. Got: %v, expected: %v", columns, cols)
   713  			}
   714  			if variableSingleUse != singleUse {
   715  				t.Errorf("Incorrect value of singleUse passed to newTabVar. Got: %v, expected: %v", singleUse, variableSingleUse)
   716  			}
   717  			callCount["createTabularVar"] = callCount["createTabularVar"] + 1
   718  			return &fakeNewGen, nil
   719  		},
   720  	}
   721  
   722  	// Fake cli args
   723  	fakeContext := newFakeContext(map[string]interface{}{
   724  		"overwrite-variable": variableOverwrite,
   725  		"single-use":         variableSingleUse,
   726  	}, cli.Args{fakeCSVPath})
   727  
   728  	// Capture output
   729  	var outBuffer bytes.Buffer
   730  	log.SetOutput(&outBuffer)
   731  	defer log.SetOutput(os.Stdout)
   732  
   733  	err := csvUpload(fakeContext, f)
   734  	if err == nil {
   735  		t.Errorf("Expected error, instead got nil.")
   736  	}
   737  	if expected := 0; callCount["getGenerators"] != expected {
   738  		t.Errorf("api.getGenerators called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   739  	}
   740  	if expected := 0; callCount["deleteGenerator"] != expected {
   741  		t.Errorf("api.deleteGenerator called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   742  	}
   743  	if expected := 0; callCount["createTabularVar"] != expected {
   744  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   745  	}
   746  	if expected := 0; callCount["addGeneratorRowsFromTable"] != expected {
   747  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   748  	}
   749  }
   750  
   751  func TestPreRunCSVUpload(t *testing.T) {
   752  	// Setup testing  stuff
   753  	createValidFakeCSV(t)
   754  	defer deleteFakeCSV(t)
   755  	tabularBatchSize = 2
   756  	variableName := "testVar"
   757  	variableOverwrite := true
   758  	variableSingleUse := false
   759  	// Data from csv
   760  	cols := []string{"test", "columns"}
   761  	firstBatch := [][]string{{"foo", "bar"}, {"baz", "wut"}}
   762  	secondBatch := [][]string{{"qwe", "asd"}, {"zxc", "jkl"}}
   763  	// Fake responses Data
   764  	fakeNewGen := rainforest.Generator{
   765  		ID:   123,
   766  		Name: variableName,
   767  		Columns: []rainforest.GeneratorColumn{
   768  			{
   769  				ID:   456,
   770  				Name: "test",
   771  			},
   772  			{
   773  				ID:   789,
   774  				Name: "columns",
   775  			},
   776  		},
   777  	}
   778  	callCount := make(map[string]int)
   779  	f := fakePI{
   780  		addGeneratorRowsFromTable: func(targetGenerator *rainforest.Generator,
   781  			targetColumns []string, rowData [][]string) error {
   782  			if !reflect.DeepEqual(targetGenerator, &fakeNewGen) {
   783  				t.Errorf("Incorrect value of targetGenerator passed. Got: %v, expected: %v", targetGenerator, fakeNewGen)
   784  			}
   785  			if !reflect.DeepEqual(targetColumns, cols) {
   786  				t.Errorf("Incorrect value of targetColumns passed. Got: %v, expected: %v", targetColumns, cols)
   787  			}
   788  			if callCount["addGeneratorRowsFromTable"] == 0 && !reflect.DeepEqual(rowData, firstBatch) {
   789  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, firstBatch)
   790  			}
   791  			if callCount["addGeneratorRowsFromTable"] == 1 && !reflect.DeepEqual(rowData, secondBatch) {
   792  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, secondBatch)
   793  			}
   794  			callCount["addGeneratorRowsFromTable"] = callCount["addGeneratorRowsFromTable"] + 1
   795  			return nil
   796  		},
   797  		getGenerators: func() ([]rainforest.Generator, error) {
   798  			callCount["getGenerators"] = callCount["getGenerators"] + 1
   799  			return []rainforest.Generator{
   800  				{
   801  					ID:   42,
   802  					Name: "Kappa",
   803  				},
   804  				{
   805  					ID:   1337,
   806  					Name: "EleGiggle",
   807  				},
   808  				fakeNewGen,
   809  			}, nil
   810  		},
   811  		deleteGenerator: func(genID int) error {
   812  			if genID != fakeNewGen.ID {
   813  				t.Errorf("Incorrect value of genID passed to delete. Got: %v, expected: %v", genID, fakeNewGen.ID)
   814  			}
   815  			callCount["deleteGenerator"] = callCount["deleteGenerator"] + 1
   816  			return nil
   817  		},
   818  		createTabularVar: func(name, description string, columns []string,
   819  			singleUse bool) (*rainforest.Generator, error) {
   820  			if variableName != name {
   821  				t.Errorf("Incorrect value of name passed to newTabVar. Got: %v, expected: %v", name, variableName)
   822  			}
   823  			if !reflect.DeepEqual(columns, cols) {
   824  				t.Errorf("Incorrect value of columns passed to newTabVar. Got: %v, expected: %v", columns, cols)
   825  			}
   826  			if variableSingleUse != singleUse {
   827  				t.Errorf("Incorrect value of singleUse passed to newTabVar. Got: %v, expected: %v", singleUse, variableSingleUse)
   828  			}
   829  			callCount["createTabularVar"] = callCount["createTabularVar"] + 1
   830  			return &fakeNewGen, nil
   831  		},
   832  	}
   833  
   834  	// Fake cli args
   835  	fakeContext := newFakeContext(map[string]interface{}{
   836  		"import-variable-csv-file": fakeCSVPath,
   837  		"import-variable-name":     variableName,
   838  		"overwrite-variable":       variableOverwrite,
   839  		"single-use":               variableSingleUse,
   840  	}, cli.Args{fakeCSVPath})
   841  
   842  	// Capture output
   843  	var outBuffer bytes.Buffer
   844  	log.SetOutput(&outBuffer)
   845  	defer log.SetOutput(os.Stdout)
   846  
   847  	err := preRunCSVUpload(fakeContext, f)
   848  	if err != nil {
   849  		t.Errorf("Unexpected error: %v", err.Error())
   850  	}
   851  	if expected := 1; callCount["getGenerators"] != expected {
   852  		t.Errorf("api.getGenerators called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   853  	}
   854  	if expected := 1; callCount["deleteGenerator"] != expected {
   855  		t.Errorf("api.deleteGenerator called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   856  	}
   857  	if expected := 1; callCount["createTabularVar"] != expected {
   858  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   859  	}
   860  	if expected := 2; callCount["addGeneratorRowsFromTable"] != expected {
   861  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   862  	}
   863  
   864  	if !strings.Contains(outBuffer.String(), "uploaded") {
   865  		t.Errorf("Expected progress updates logged out (containing 'uploaded'), got %v", outBuffer.String())
   866  	}
   867  	if !strings.Contains(outBuffer.String(), "overwriting") {
   868  		t.Errorf("Expected information about overwriting variable, got %v", outBuffer.String())
   869  	}
   870  }
   871  
   872  func TestPreRunCSVUpload_MissingName(t *testing.T) {
   873  	// Setup testing  stuff
   874  	createValidFakeCSV(t)
   875  	defer deleteFakeCSV(t)
   876  	tabularBatchSize = 2
   877  	variableName := "testVar"
   878  	variableOverwrite := true
   879  	variableSingleUse := false
   880  	// Data from csv
   881  	cols := []string{"test", "columns"}
   882  	firstBatch := [][]string{{"foo", "bar"}, {"baz", "wut"}}
   883  	secondBatch := [][]string{{"qwe", "asd"}, {"zxc", "jkl"}}
   884  	// Fake responses Data
   885  	fakeNewGen := rainforest.Generator{
   886  		ID:   123,
   887  		Name: variableName,
   888  		Columns: []rainforest.GeneratorColumn{
   889  			{
   890  				ID:   456,
   891  				Name: "test",
   892  			},
   893  			{
   894  				ID:   789,
   895  				Name: "columns",
   896  			},
   897  		},
   898  	}
   899  	callCount := make(map[string]int)
   900  	f := fakePI{
   901  		addGeneratorRowsFromTable: func(targetGenerator *rainforest.Generator,
   902  			targetColumns []string, rowData [][]string) error {
   903  			if !reflect.DeepEqual(targetGenerator, &fakeNewGen) {
   904  				t.Errorf("Incorrect value of targetGenerator passed. Got: %v, expected: %v", targetGenerator, fakeNewGen)
   905  			}
   906  			if !reflect.DeepEqual(targetColumns, cols) {
   907  				t.Errorf("Incorrect value of targetColumns passed. Got: %v, expected: %v", targetColumns, cols)
   908  			}
   909  			if callCount["addGeneratorRowsFromTable"] == 0 && !reflect.DeepEqual(rowData, firstBatch) {
   910  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, firstBatch)
   911  			}
   912  			if callCount["addGeneratorRowsFromTable"] == 1 && !reflect.DeepEqual(rowData, secondBatch) {
   913  				t.Errorf("Incorrect value of rowData passed. Got: %v, expected: %v", rowData, secondBatch)
   914  			}
   915  			callCount["addGeneratorRowsFromTable"] = callCount["addGeneratorRowsFromTable"] + 1
   916  			return nil
   917  		},
   918  		getGenerators: func() ([]rainforest.Generator, error) {
   919  			callCount["getGenerators"] = callCount["getGenerators"] + 1
   920  			return []rainforest.Generator{
   921  				{
   922  					ID:   42,
   923  					Name: "Kappa",
   924  				},
   925  				{
   926  					ID:   1337,
   927  					Name: "EleGiggle",
   928  				},
   929  				fakeNewGen,
   930  			}, nil
   931  		},
   932  		deleteGenerator: func(genID int) error {
   933  			if genID != fakeNewGen.ID {
   934  				t.Errorf("Incorrect value of genID passed to delete. Got: %v, expected: %v", genID, fakeNewGen.ID)
   935  			}
   936  			callCount["deleteGenerator"] = callCount["deleteGenerator"] + 1
   937  			return nil
   938  		},
   939  		createTabularVar: func(name, description string, columns []string,
   940  			singleUse bool) (*rainforest.Generator, error) {
   941  			if variableName != name {
   942  				t.Errorf("Incorrect value of name passed to newTabVar. Got: %v, expected: %v", name, variableName)
   943  			}
   944  			if !reflect.DeepEqual(columns, cols) {
   945  				t.Errorf("Incorrect value of columns passed to newTabVar. Got: %v, expected: %v", columns, cols)
   946  			}
   947  			if variableSingleUse != singleUse {
   948  				t.Errorf("Incorrect value of singleUse passed to newTabVar. Got: %v, expected: %v", singleUse, variableSingleUse)
   949  			}
   950  			callCount["createTabularVar"] = callCount["createTabularVar"] + 1
   951  			return &fakeNewGen, nil
   952  		},
   953  	}
   954  
   955  	// Fake cli args
   956  	fakeContext := newFakeContext(map[string]interface{}{
   957  		"overwrite-variable": variableOverwrite,
   958  		"single-use":         variableSingleUse,
   959  	}, cli.Args{fakeCSVPath})
   960  
   961  	// Capture output
   962  	var outBuffer bytes.Buffer
   963  	log.SetOutput(&outBuffer)
   964  	defer log.SetOutput(os.Stdout)
   965  
   966  	err := preRunCSVUpload(fakeContext, f)
   967  	if err != nil {
   968  		t.Errorf("Unexpected error: %v", err.Error())
   969  	}
   970  	if expected := 0; callCount["getGenerators"] != expected {
   971  		t.Errorf("api.getGenerators called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   972  	}
   973  	if expected := 0; callCount["deleteGenerator"] != expected {
   974  		t.Errorf("api.deleteGenerator called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   975  	}
   976  	if expected := 0; callCount["createTabularVar"] != expected {
   977  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   978  	}
   979  	if expected := 0; callCount["addGeneratorRowsFromTable"] != expected {
   980  		t.Errorf("api.createTabularVar called invalid number of times: %v, expected %v", callCount["getGenerators"], expected)
   981  	}
   982  }