github.com/0chain/gosdk@v1.17.11/zboxcore/sdk/allocation_test.go (about)

     1  package sdk
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"encoding/hex"
     7  	"encoding/json"
     8  	"io"
     9  	"io/fs"
    10  	"io/ioutil"
    11  	"log"
    12  	"net/http"
    13  	"os"
    14  	"strconv"
    15  	"strings"
    16  	"sync"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/0chain/gosdk/dev/blobber"
    21  	"github.com/0chain/gosdk/dev/blobber/model"
    22  	"github.com/0chain/gosdk/zboxcore/encryption"
    23  	"golang.org/x/crypto/sha3"
    24  
    25  	"github.com/0chain/errors"
    26  	"github.com/0chain/gosdk/core/common"
    27  	"github.com/0chain/gosdk/core/sys"
    28  
    29  	"github.com/0chain/gosdk/core/zcncrypto"
    30  	"github.com/0chain/gosdk/zboxcore/blockchain"
    31  	zclient "github.com/0chain/gosdk/zboxcore/client"
    32  	"github.com/0chain/gosdk/zboxcore/fileref"
    33  	"github.com/0chain/gosdk/zboxcore/mocks"
    34  	"github.com/0chain/gosdk/zboxcore/zboxutil"
    35  	"github.com/stretchr/testify/mock"
    36  	"github.com/stretchr/testify/require"
    37  )
    38  
    39  const (
    40  	tokenUnit          = 10000000000.0
    41  	mockAllocationId   = "mock allocation id"
    42  	mockAllocationTxId = "mock transaction id"
    43  	mockClientId       = "mock client id"
    44  	mockClientKey      = "mock client key"
    45  	mockBlobberId      = "mock blobber id"
    46  	mockBlobberUrl     = "mockBlobberUrl"
    47  	mockLookupHash     = "mock lookup hash"
    48  	mockAllocationRoot = "mock allocation root"
    49  	mockFileRefName    = "mock file ref name"
    50  	numBlobbers        = 4
    51  )
    52  
    53  func setupMockGetFileMetaResponse(
    54  	t *testing.T, mockClient *mocks.HttpClient, funcName string,
    55  	testCaseName string, a *Allocation, httpMethod string,
    56  	statusCode int, body []byte) {
    57  
    58  	for i := 0; i < numBlobbers; i++ {
    59  		url := funcName + testCaseName + mockBlobberUrl + strconv.Itoa(i) + zboxutil.FILE_META_ENDPOINT
    60  		mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
    61  			log.Println(req.URL.String(), url)
    62  			return req.Method == httpMethod &&
    63  				strings.HasPrefix(req.URL.String(), url)
    64  		})).Return(&http.Response{
    65  			StatusCode: statusCode,
    66  			Body:       ioutil.NopCloser(bytes.NewReader(body)),
    67  		}, nil).Once()
    68  	}
    69  }
    70  
    71  func setupMockHttpResponse(
    72  	t *testing.T, mockClient *mocks.HttpClient, funcName string,
    73  	testCaseName string, a *Allocation, httpMethod string,
    74  	statusCode int, body []byte) {
    75  
    76  	for i := 0; i < numBlobbers; i++ {
    77  		mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
    78  			return req.Method == httpMethod && strings.Contains(req.URL.String(), "list=true")
    79  		})).Return(&http.Response{
    80  			StatusCode: statusCode,
    81  			Body:       io.NopCloser(bytes.NewReader(body)),
    82  		}, nil).Once()
    83  	}
    84  
    85  	for i := 0; i < numBlobbers; i++ {
    86  		url := funcName + testCaseName + mockBlobberUrl + strconv.Itoa(i)
    87  		mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
    88  			return req.Method == httpMethod &&
    89  				strings.Contains(req.URL.String(), url)
    90  		})).Return(&http.Response{
    91  			StatusCode: statusCode,
    92  			Body:       io.NopCloser(bytes.NewReader(body)),
    93  		}, nil).Once()
    94  	}
    95  }
    96  
    97  func setupMockCommitRequest(a *Allocation) {
    98  	commitChan = make(map[string]chan *CommitRequest)
    99  	for _, blobber := range a.Blobbers {
   100  		if _, ok := commitChan[blobber.ID]; !ok {
   101  			commitChan[blobber.ID] = make(chan *CommitRequest, 1)
   102  			blobberChan := commitChan[blobber.ID]
   103  			go func(c <-chan *CommitRequest, blID string) {
   104  				for {
   105  					cm := <-c
   106  					if cm != nil {
   107  						cm.result = &CommitResult{
   108  							Success: true,
   109  						}
   110  						if cm.wg != nil {
   111  							cm.wg.Done()
   112  						}
   113  					}
   114  				}
   115  			}(blobberChan, blobber.ID)
   116  		}
   117  	}
   118  }
   119  
   120  func setupMockWriteLockRequest(a *Allocation, mockClient *mocks.HttpClient) {
   121  
   122  	for _, blobber := range a.Blobbers {
   123  		url := blobber.Baseurl + zboxutil.WM_LOCK_ENDPOINT
   124  		url = strings.TrimRight(url, "/")
   125  		mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   126  			return strings.Contains(req.URL.String(), url)
   127  		})).Return(&http.Response{
   128  			StatusCode: http.StatusOK,
   129  			Body: func() io.ReadCloser {
   130  				resp := &WMLockResult{
   131  					Status: WMLockStatusOK,
   132  				}
   133  				respBuf, _ := json.Marshal(resp)
   134  				return io.NopCloser(bytes.NewReader(respBuf))
   135  			}(),
   136  		}, nil)
   137  	}
   138  }
   139  
   140  func setupMockFile(t *testing.T, path string) (teardown func(t *testing.T)) {
   141  	_, err := os.Create(path)
   142  	require.Nil(t, err)
   143  	err = ioutil.WriteFile(path, []byte("mockActualHash"), os.ModePerm)
   144  	require.Nil(t, err)
   145  	return func(t *testing.T) {
   146  		os.Remove(path)
   147  	}
   148  }
   149  
   150  func setupMockRollback(a *Allocation, mockClient *mocks.HttpClient) {
   151  
   152  	for _, blobber := range a.Blobbers {
   153  		url := blobber.Baseurl + zboxutil.LATEST_WRITE_MARKER_ENDPOINT
   154  		url = strings.TrimRight(url, "/")
   155  		mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   156  			return strings.Contains(req.URL.String(), url)
   157  		})).Return(&http.Response{
   158  			StatusCode: http.StatusOK,
   159  			Body: func() io.ReadCloser {
   160  				s := `{"latest_write_marker":null,"prev_write_marker":null}`
   161  				return ioutil.NopCloser(bytes.NewReader([]byte(s)))
   162  			}(),
   163  		}, nil)
   164  
   165  		newUrl := blobber.Baseurl + zboxutil.ROLLBACK_ENDPOINT
   166  		newUrl = strings.TrimRight(newUrl, "/")
   167  		mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   168  			return strings.Contains(req.URL.String(), newUrl)
   169  		})).Return(&http.Response{
   170  			StatusCode: http.StatusOK,
   171  			Body:       ioutil.NopCloser(bytes.NewReader(nil)),
   172  		}, nil)
   173  	}
   174  
   175  }
   176  
   177  func setupMockFileAndReferencePathResult(t *testing.T, allocationID, name string) (teardown func(t *testing.T)) {
   178  	var buf = []byte("mockActualHash")
   179  	h := sha3.New256()
   180  	f, _ := os.Create(name)
   181  	w := io.MultiWriter(h, f)
   182  	//nolint: errcheck
   183  	w.Write(buf)
   184  
   185  	cancel := blobber.MockReferencePathResult(allocationID, &model.Ref{
   186  		AllocationID: allocationID,
   187  		Type:         model.DIRECTORY,
   188  		Name:         "/",
   189  		Path:         "/",
   190  		PathLevel:    1,
   191  		ParentPath:   "",
   192  		Children: []*model.Ref{
   193  			{
   194  				AllocationID:   allocationID,
   195  				Name:           name,
   196  				Type:           model.FILE,
   197  				Path:           "/" + name,
   198  				ActualFileSize: int64(len(buf)),
   199  				ActualFileHash: hex.EncodeToString(h.Sum(nil)),
   200  				ChunkSize:      CHUNK_SIZE,
   201  				PathLevel:      2,
   202  				ParentPath:     "/",
   203  			},
   204  		},
   205  	})
   206  
   207  	return func(t *testing.T) {
   208  		cancel()
   209  		os.Remove(name)
   210  	}
   211  }
   212  
   213  func TestGetMinMaxWriteReadSuccess(t *testing.T) {
   214  	var ssc = newTestAllocation()
   215  	ssc.DataShards = 5
   216  	ssc.ParityShards = 4
   217  
   218  	ssc.initialized = true
   219  	sdkInitialized = true
   220  	require.NotNil(t, ssc.BlobberDetails)
   221  
   222  	t.Run("Success minR, minW", func(t *testing.T) {
   223  		minW, minR, err := ssc.GetMinWriteRead()
   224  		require.NoError(t, err)
   225  		require.Equal(t, 0.01, minW)
   226  		require.Equal(t, 0.01, minR)
   227  	})
   228  
   229  	t.Run("Success maxR, maxW", func(t *testing.T) {
   230  		maxW, maxR, err := ssc.GetMaxWriteRead()
   231  		require.NoError(t, err)
   232  		require.Equal(t, 0.01, maxW)
   233  		require.Equal(t, 0.01, maxR)
   234  	})
   235  
   236  	t.Run("Error / No Blobbers", func(t *testing.T) {
   237  		var (
   238  			ssc = newTestAllocationEmptyBlobbers()
   239  			err error
   240  		)
   241  		ssc.initialized = true
   242  		_, _, err = ssc.GetMinWriteRead()
   243  		require.Error(t, err)
   244  	})
   245  
   246  	t.Run("Error / Empty Blobbers", func(t *testing.T) {
   247  		var err error
   248  		ssc.initialized = false
   249  		_, _, err = ssc.GetMinWriteRead()
   250  		require.Error(t, err)
   251  	})
   252  
   253  	t.Run("Error / Not Initialized", func(t *testing.T) {
   254  		var err error
   255  		ssc.initialized = false
   256  		_, _, err = ssc.GetMinWriteRead()
   257  		require.Error(t, err)
   258  	})
   259  }
   260  
   261  func TestGetMaxMinStorageCostSuccess(t *testing.T) {
   262  	var ssc = newTestAllocation()
   263  	ssc.DataShards = 4
   264  	ssc.ParityShards = 2
   265  
   266  	ssc.initialized = true
   267  	sdkInitialized = true
   268  
   269  	t.Run("Storage cost", func(t *testing.T) {
   270  		cost, err := ssc.GetMaxStorageCost(100 * GB)
   271  		require.NoError(t, err)
   272  		require.Equal(t, 1.5, cost)
   273  	})
   274  }
   275  
   276  func newTestAllocationEmptyBlobbers() (ssc *Allocation) {
   277  	ssc = new(Allocation)
   278  	ssc.Expiration = 0
   279  	ssc.ID = "ID"
   280  	ssc.BlobberDetails = make([]*BlobberAllocation, 0)
   281  	return ssc
   282  }
   283  
   284  func newTestAllocation() (ssc *Allocation) {
   285  	ssc = new(Allocation)
   286  	ssc.Expiration = 0
   287  	ssc.ID = "ID"
   288  	ssc.BlobberDetails = newBlobbersDetails()
   289  	return ssc
   290  }
   291  
   292  func newBlobbersDetails() (blobbers []*BlobberAllocation) {
   293  	blobberDetails := make([]*BlobberAllocation, 0)
   294  
   295  	for i := 1; i <= 1; i++ {
   296  		var balloc BlobberAllocation
   297  		balloc.Size = 1000
   298  
   299  		balloc.Terms = Terms{ReadPrice: common.Balance(100000000), WritePrice: common.Balance(100000000)}
   300  		blobberDetails = append(blobberDetails, &balloc)
   301  	}
   302  
   303  	return blobberDetails
   304  }
   305  
   306  type MockFile struct {
   307  	os.FileInfo
   308  }
   309  
   310  func (m MockFile) Size() int64 { return 10 }
   311  
   312  func TestPriceRange_IsValid(t *testing.T) {
   313  	type fields struct {
   314  		Min uint64
   315  		Max uint64
   316  	}
   317  	tests := []struct {
   318  		name   string
   319  		fields fields
   320  		want   bool
   321  	}{
   322  		{
   323  			"Test_Valid_InRange",
   324  			fields{
   325  				Min: 0,
   326  				Max: 50,
   327  			},
   328  			true,
   329  		},
   330  		{
   331  			"Test_Valid_At_Once_Value",
   332  			fields{
   333  				Min: 10,
   334  				Max: 10,
   335  			},
   336  			true,
   337  		},
   338  		{
   339  			"Test_Invalid_InRange",
   340  			fields{
   341  				Min: 10,
   342  				Max: 5,
   343  			},
   344  			false,
   345  		},
   346  	}
   347  	for _, tt := range tests {
   348  		t.Run(tt.name, func(t *testing.T) {
   349  			pr := &PriceRange{
   350  				Min: tt.fields.Min,
   351  				Max: tt.fields.Max,
   352  			}
   353  			got := pr.IsValid()
   354  			require := require.New(t)
   355  			var check = require.False
   356  			if tt.want {
   357  				check = require.True
   358  			}
   359  			check(got)
   360  		})
   361  	}
   362  }
   363  
   364  func TestAllocation_InitAllocation(t *testing.T) {
   365  	a := Allocation{
   366  		FileOptions: 63,
   367  	}
   368  	a.InitAllocation()
   369  	require.New(t).NotZero(a)
   370  }
   371  
   372  func TestAllocation_dispatchWork(t *testing.T) {
   373  	a := Allocation{DataShards: 2, ParityShards: 2, downloadChan: make(chan *DownloadRequest), repairChan: make(chan *RepairRequest)}
   374  	t.Run("Test_Cover_Context_Canceled", func(t *testing.T) {
   375  		ctx, cancelFn := context.WithCancel(context.Background())
   376  		go a.dispatchWork(ctx)
   377  		cancelFn()
   378  	})
   379  	t.Run("Test_Cover_Download_Request", func(t *testing.T) {
   380  		ctx, ctxCncl := context.WithCancel(context.Background())
   381  		go a.dispatchWork(context.Background())
   382  		a.downloadChan <- &DownloadRequest{ctx: ctx, ctxCncl: ctxCncl}
   383  	})
   384  	t.Run("Test_Cover_Repair_Request", func(t *testing.T) {
   385  		go a.dispatchWork(context.Background())
   386  		a.repairChan <- &RepairRequest{listDir: &ListResult{}}
   387  	})
   388  }
   389  
   390  func TestAllocation_GetStats(t *testing.T) {
   391  	stats := &AllocationStats{}
   392  	a := &Allocation{
   393  		Stats: stats,
   394  	}
   395  	got := a.GetStats()
   396  	require.New(t).Same(stats, got)
   397  }
   398  
   399  func TestAllocation_GetBlobberStats(t *testing.T) {
   400  	var mockClient = mocks.HttpClient{}
   401  	zboxutil.Client = &mockClient
   402  
   403  	client := zclient.GetClient()
   404  	client.Wallet = &zcncrypto.Wallet{
   405  		ClientID:  mockClientId,
   406  		ClientKey: mockClientKey,
   407  	}
   408  
   409  	tests := []struct {
   410  		name  string
   411  		setup func(*testing.T, string)
   412  	}{
   413  		{
   414  			name: "Test_Success",
   415  			setup: func(t *testing.T, testName string) {
   416  				mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   417  					return strings.HasPrefix(req.URL.Path, "TestAllocation_GetBlobberStats"+testName)
   418  				})).Return(&http.Response{
   419  					Body: func() io.ReadCloser {
   420  						jsonFR, err := json.Marshal(&BlobberAllocationStats{
   421  							ID: mockAllocationId,
   422  							Tx: mockAllocationTxId,
   423  						})
   424  						require.NoError(t, err)
   425  						return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
   426  					}(),
   427  					StatusCode: http.StatusOK,
   428  				}, nil)
   429  			},
   430  		},
   431  	}
   432  	for _, tt := range tests {
   433  		t.Run(tt.name, func(t *testing.T) {
   434  			require := require.New(t)
   435  			tt.setup(t, tt.name)
   436  			a := &Allocation{
   437  				ID: mockAllocationId,
   438  				Tx: mockAllocationTxId,
   439  			}
   440  			a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   441  				ID:      tt.name + mockBlobberId,
   442  				Baseurl: "TestAllocation_GetBlobberStats" + tt.name + mockBlobberUrl,
   443  			})
   444  			got := a.GetBlobberStats()
   445  			require.NotEmptyf(got, "Error no blobber stats result found")
   446  
   447  			expected := make(map[string]*BlobberAllocationStats, 1)
   448  			expected["TestAllocation_GetBlobberStats"+tt.name+mockBlobberUrl] = &BlobberAllocationStats{
   449  				ID:         mockAllocationId,
   450  				Tx:         mockAllocationTxId,
   451  				BlobberID:  tt.name + mockBlobberId,
   452  				BlobberURL: "TestAllocation_GetBlobberStats" + tt.name + mockBlobberUrl,
   453  			}
   454  
   455  			for key, val := range expected {
   456  				require.NotNilf(got[key], "Error result map must be contain key %v", key)
   457  				require.EqualValues(val, got[key])
   458  			}
   459  		})
   460  	}
   461  }
   462  
   463  func TestAllocation_isInitialized(t *testing.T) {
   464  	tests := []struct {
   465  		name                                        string
   466  		sdkInitialized, allocationInitialized, want bool
   467  	}{
   468  		{
   469  			"Test_Initialized",
   470  			true, true, true,
   471  		},
   472  		{
   473  			"Test_SDK_Uninitialized",
   474  			false, true, false,
   475  		},
   476  		{
   477  			"Test_Allocation_Uninitialized",
   478  			true, false, false,
   479  		},
   480  		{
   481  			"Test_Both_SDK_And_Allocation_Uninitialized",
   482  			false, false, false,
   483  		},
   484  	}
   485  	for _, tt := range tests {
   486  		t.Run(tt.name, func(t *testing.T) {
   487  			originalSDKInitialized := sdkInitialized
   488  			defer func() { sdkInitialized = originalSDKInitialized }()
   489  			sdkInitialized = tt.sdkInitialized
   490  			a := &Allocation{initialized: tt.allocationInitialized}
   491  			got := a.isInitialized()
   492  			require := require.New(t)
   493  			if tt.want {
   494  				require.True(got, `Error a.isInitialized() should returns "true"", but got "false"`)
   495  				return
   496  			}
   497  			require.False(got, `Error a.isInitialized() should returns "false"", but got "true"`)
   498  		})
   499  	}
   500  }
   501  
   502  // Uncomment tests later on after critical issues are fixed
   503  // func TestAllocation_CreateDir(t *testing.T) {
   504  // 	const mockLocalPath = "/test"
   505  // 	require := require.New(t)
   506  // 	if teardown := setupMockFile(t, mockLocalPath); teardown != nil {
   507  // 		defer teardown(t)
   508  // 	}
   509  // 	a := &Allocation{
   510  // 		ParityShards: 2,
   511  // 		DataShards:   2,
   512  // 	}
   513  // 	setupMockAllocation(t, a)
   514  
   515  // 	var mockClient = mocks.HttpClient{}
   516  // 	zboxutil.Client = &mockClient
   517  
   518  // 	client := zclient.GetClient()
   519  // 	client.Wallet = &zcncrypto.Wallet{
   520  // 		ClientID:  mockClientId,
   521  // 		ClientKey: mockClientKey,
   522  // 	}
   523  
   524  // 	mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   525  // 		return strings.HasPrefix(req.URL.Path, "TestAllocation_CreateDir")
   526  // 	})).Return(&http.Response{
   527  // 		StatusCode: http.StatusOK,
   528  // 		Body:       ioutil.NopCloser(bytes.NewReader([]byte(""))),
   529  // 	}, nil)
   530  
   531  // 	for i := 0; i < numBlobbers; i++ {
   532  // 		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   533  // 			ID:      mockBlobberId + strconv.Itoa(i),
   534  // 			Baseurl: "TestAllocation_CreateDir" + mockBlobberUrl + strconv.Itoa(i),
   535  // 		})
   536  // 	}
   537  // 	err := a.CreateDir(mockLocalPath)
   538  // 	require.NoErrorf(err, "Unexpected error %v", err)
   539  // }
   540  
   541  func TestAllocation_RepairRequired(t *testing.T) {
   542  	const (
   543  		mockActualHash = "4041e3eeb170751544a47af4e4f9d374e76cee1d"
   544  	)
   545  
   546  	var mockClient = mocks.HttpClient{}
   547  	zboxutil.Client = &mockClient
   548  
   549  	client := zclient.GetClient()
   550  	client.Wallet = &zcncrypto.Wallet{
   551  		ClientID:  mockClientId,
   552  		ClientKey: mockClientKey,
   553  	}
   554  
   555  	tests := []struct {
   556  		name                          string
   557  		setup                         func(*testing.T, string, *Allocation) (teardown func(*testing.T))
   558  		remotePath                    string
   559  		wantFound                     uint64
   560  		wantFileRef                   *fileref.FileRef
   561  		wantMatchesConsensus, wantErr bool
   562  		errMsg                        string
   563  	}{
   564  		{
   565  			name: "Test_Not_Repair_Required_Success",
   566  			setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) {
   567  				for i := 0; i < numBlobbers; i++ {
   568  					url := "TestAllocation_RepairRequired" + testCaseName + mockBlobberUrl + strconv.Itoa(i)
   569  					a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   570  						Baseurl: url,
   571  					})
   572  					mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   573  						return strings.HasPrefix(req.URL.Path, url)
   574  					})).Return(&http.Response{
   575  						StatusCode: http.StatusOK,
   576  						Body: func() io.ReadCloser {
   577  							respString := `{"file_meta_hash":"` + mockActualHash + `"}`
   578  							return ioutil.NopCloser(bytes.NewReader([]byte(respString)))
   579  						}(),
   580  					}, nil)
   581  				}
   582  				return nil
   583  			},
   584  			remotePath:           "/x.txt",
   585  			wantFound:            0xf,
   586  			wantMatchesConsensus: false,
   587  			wantErr:              false,
   588  		},
   589  		{
   590  			name: "Test_Uninitialized_Failed",
   591  			setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) {
   592  				a.initialized = false
   593  				return func(t *testing.T) { a.initialized = true }
   594  			},
   595  			remotePath:           "/",
   596  			wantFound:            0,
   597  			wantMatchesConsensus: false,
   598  			wantErr:              true,
   599  			errMsg:               "sdk_not_initialized: Please call InitStorageSDK Init and use GetAllocation to get the allocation object",
   600  		},
   601  		{
   602  			name: "Test_Repair_Required_Success",
   603  			setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) {
   604  				for i := 0; i < numBlobbers; i++ {
   605  					var hash string
   606  					if i < numBlobbers-1 {
   607  						hash = mockActualHash
   608  					}
   609  					url := "TestAllocation_RepairRequired" + testCaseName + mockBlobberUrl + strconv.Itoa(i)
   610  					a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   611  						Baseurl: url,
   612  					})
   613  					mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   614  						return strings.HasPrefix(req.URL.Path, url)
   615  					})).Return(&http.Response{
   616  						StatusCode: http.StatusOK,
   617  						Body: func(hash string) io.ReadCloser {
   618  							respString := `{"file_meta_hash":"` + hash + `"}`
   619  							return ioutil.NopCloser(bytes.NewReader([]byte(respString)))
   620  						}(hash),
   621  					}, nil)
   622  				}
   623  				return nil
   624  			},
   625  			remotePath:           "/",
   626  			wantFound:            0x7,
   627  			wantMatchesConsensus: true,
   628  			wantErr:              false,
   629  		},
   630  		{
   631  			name: "Test_Remote_File_Not_Found_Failed",
   632  			setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) {
   633  				for i := 0; i < numBlobbers; i++ {
   634  					url := "TestAllocation_RepairRequired" + testCaseName + mockBlobberUrl + strconv.Itoa(i)
   635  					a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   636  						Baseurl: url,
   637  					})
   638  					mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   639  						return strings.HasPrefix(req.URL.Path, url)
   640  					})).Return(&http.Response{
   641  						StatusCode: http.StatusBadRequest,
   642  						Body:       ioutil.NopCloser(bytes.NewReader([]byte(""))),
   643  					}, nil)
   644  				}
   645  				return nil
   646  			},
   647  			remotePath:           "/x.txt",
   648  			wantFound:            0x0,
   649  			wantMatchesConsensus: false,
   650  			wantErr:              true,
   651  			errMsg:               "File not found for the given remotepath",
   652  		},
   653  	}
   654  	for _, tt := range tests {
   655  		t.Run(tt.name, func(t *testing.T) {
   656  			require := require.New(t)
   657  			a := &Allocation{
   658  				DataShards:   2,
   659  				ParityShards: 2,
   660  				FileOptions:  63,
   661  			}
   662  			a.InitAllocation()
   663  			sdkInitialized = true
   664  			if tt.setup != nil {
   665  				if teardown := tt.setup(t, tt.name, a); teardown != nil {
   666  					defer teardown(t)
   667  				}
   668  			}
   669  			found, _, matchesConsensus, fileRef, err := a.RepairRequired(tt.remotePath)
   670  			require.Equal(zboxutil.NewUint128(tt.wantFound), found, "found value must be same")
   671  			if tt.wantMatchesConsensus {
   672  				require.True(tt.wantMatchesConsensus, matchesConsensus)
   673  			} else {
   674  				require.False(tt.wantMatchesConsensus, matchesConsensus)
   675  			}
   676  			require.EqualValues(tt.wantErr, err != nil)
   677  			if err != nil {
   678  				require.EqualValues(tt.errMsg, errors.Top(err))
   679  				return
   680  			}
   681  			require.EqualValues(mockActualHash, fileRef.FileMetaHash)
   682  			require.NoErrorf(err, "Unexpected error %v", err)
   683  		})
   684  	}
   685  }
   686  
   687  func TestAllocation_DownloadFileToFileHandler(t *testing.T) {
   688  	const (
   689  		mockActualHash     = "mockActualHash"
   690  		mockRemoteFilePath = "1.txt"
   691  	)
   692  
   693  	var mockFile = &sys.MemFile{Name: "mockFile", Mode: fs.ModePerm, ModTime: time.Now()}
   694  	var mockClient = mocks.HttpClient{}
   695  	zboxutil.Client = &mockClient
   696  
   697  	client := zclient.GetClient()
   698  	client.Wallet = &zcncrypto.Wallet{
   699  		ClientID:  mockClientId,
   700  		ClientKey: mockClientKey,
   701  	}
   702  
   703  	type parameters struct {
   704  		fileHandler    sys.File
   705  		remotePath     string
   706  		statusCallback StatusCallback
   707  	}
   708  	tests := []struct {
   709  		name       string
   710  		parameters parameters
   711  		setup      func(*testing.T, string, parameters, *Allocation) (teardown func(*testing.T))
   712  		wantErr    bool
   713  		errMsg     string
   714  	}{
   715  		{
   716  			name: "Test_Download_File_Success",
   717  			parameters: parameters{
   718  				fileHandler:    mockFile,
   719  				remotePath:     mockRemoteFilePath,
   720  				statusCallback: nil,
   721  			},
   722  			setup: func(t *testing.T, testCaseName string, p parameters, a *Allocation) (teardown func(t *testing.T)) {
   723  				for i := 0; i < numBlobbers; i++ {
   724  					url := "TestAllocation_DownloadToFileHandler" + mockBlobberUrl + strconv.Itoa(i)
   725  					mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   726  						return strings.HasPrefix(req.URL.Path, url)
   727  					})).Return(&http.Response{
   728  						StatusCode: http.StatusOK,
   729  						Body: func() io.ReadCloser {
   730  							jsonFR, err := json.Marshal(&fileref.FileRef{
   731  								ActualFileHash: mockActualHash,
   732  							})
   733  							require.NoError(t, err)
   734  							return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
   735  						}(),
   736  					}, nil)
   737  				}
   738  				return nil
   739  			},
   740  		},
   741  	}
   742  	for _, tt := range tests {
   743  		t.Run(tt.name, func(t *testing.T) {
   744  			require := require.New(t)
   745  			a := &Allocation{}
   746  			setupMockAllocation(t, a)
   747  			for i := 0; i < numBlobbers; i++ {
   748  				a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   749  					ID:      tt.name + strconv.Itoa(i),
   750  					Baseurl: "TestAllocation_DownloadToFileHandler" + mockBlobberUrl + strconv.Itoa(i),
   751  				})
   752  			}
   753  			if m := tt.setup; m != nil {
   754  				if teardown := m(t, tt.name, tt.parameters, a); teardown != nil {
   755  					defer teardown(t)
   756  				}
   757  			}
   758  
   759  			err := a.DownloadFileToFileHandler(tt.parameters.fileHandler, tt.parameters.remotePath, true, tt.parameters.statusCallback, false)
   760  			require.EqualValues(tt.wantErr, err != nil)
   761  			if err != nil {
   762  				require.EqualValues(tt.errMsg, errors.Top(err))
   763  				return
   764  			}
   765  			require.NoErrorf(err, "Unexpected error: %v", err)
   766  		})
   767  	}
   768  }
   769  
   770  func TestAllocation_DownloadFile(t *testing.T) {
   771  	const (
   772  		mockActualHash     = "mockActualHash"
   773  		mockLocalPath      = "DownloadFile"
   774  		mockRemoteFilePath = "1.txt"
   775  	)
   776  	var mockClient = mocks.HttpClient{}
   777  	zboxutil.Client = &mockClient
   778  
   779  	client := zclient.GetClient()
   780  	client.Wallet = &zcncrypto.Wallet{
   781  		ClientID:  mockClientId,
   782  		ClientKey: mockClientKey,
   783  	}
   784  
   785  	require := require.New(t)
   786  	a := &Allocation{
   787  		ParityShards: 2,
   788  		DataShards:   2,
   789  	}
   790  	setupMockAllocation(t, a)
   791  
   792  	for i := 0; i < numBlobbers; i++ {
   793  		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   794  			ID:      mockBlobberId + strconv.Itoa(i),
   795  			Baseurl: mockBlobberUrl + strconv.Itoa(i),
   796  		})
   797  	}
   798  	for i := 0; i < numBlobbers; i++ {
   799  		url := mockBlobberUrl + strconv.Itoa(i)
   800  		mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   801  			return strings.HasPrefix(req.URL.Path, url)
   802  		})).Return(&http.Response{
   803  			StatusCode: http.StatusOK,
   804  			Body: func() io.ReadCloser {
   805  				jsonFR, err := json.Marshal(&fileref.FileRef{
   806  					ActualFileHash: mockActualHash,
   807  				})
   808  				require.NoError(err)
   809  				return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
   810  			}(),
   811  		}, nil)
   812  	}
   813  
   814  	defer os.RemoveAll(mockLocalPath) //nolint: errcheck
   815  	err := a.DownloadFile(mockLocalPath, mockRemoteFilePath, false, nil, false)
   816  	require.NoErrorf(err, "Unexpected error %v", err)
   817  }
   818  
   819  func TestAllocation_DownloadFileByBlock(t *testing.T) {
   820  	const (
   821  		mockLocalPath      = "DownloadFileByBlock"
   822  		mockRemoteFilePath = "1.txt"
   823  	)
   824  	var mockClient = mocks.HttpClient{}
   825  	zboxutil.Client = &mockClient
   826  
   827  	client := zclient.GetClient()
   828  	client.Wallet = &zcncrypto.Wallet{
   829  		ClientID:  mockClientId,
   830  		ClientKey: mockClientKey,
   831  	}
   832  
   833  	require := require.New(t)
   834  	a := &Allocation{
   835  		ParityShards: 2,
   836  		DataShards:   2,
   837  	}
   838  	setupMockAllocation(t, a)
   839  
   840  	for i := 0; i < numBlobbers; i++ {
   841  		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   842  			ID:      mockBlobberId + strconv.Itoa(i),
   843  			Baseurl: mockBlobberUrl + strconv.Itoa(i),
   844  		})
   845  	}
   846  	defer os.RemoveAll(mockLocalPath) //nolint: errcheck
   847  	err := a.DownloadFileByBlock(mockLocalPath, mockRemoteFilePath, 1, 0, numBlockDownloads, true, nil, false)
   848  	require.NoErrorf(err, "Unexpected error %v", err)
   849  }
   850  
   851  func TestAllocation_DownloadThumbnail(t *testing.T) {
   852  	const (
   853  		mockLocalPath      = "DownloadThumbnail"
   854  		mockRemoteFilePath = "1.txt"
   855  	)
   856  	require := require.New(t)
   857  	a := &Allocation{}
   858  	setupMockAllocation(t, a)
   859  
   860  	for i := 0; i < numBlobbers; i++ {
   861  		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   862  			ID:      strconv.Itoa(i),
   863  			Baseurl: "TestAllocation_DownloadThumbnail" + mockBlobberUrl + strconv.Itoa(i),
   864  		})
   865  	}
   866  
   867  	defer os.RemoveAll(mockLocalPath) //nolint: errcheck
   868  	err := a.DownloadThumbnail(mockLocalPath, mockRemoteFilePath, true, nil, false)
   869  	require.NoErrorf(err, "Unexpected error %v", err)
   870  }
   871  
   872  func TestAllocation_downloadFile(t *testing.T) {
   873  	const (
   874  		mockActualHash     = "mockActualHash"
   875  		mockLocalPath      = "alloc"
   876  		mockRemoteFilePath = "1.txt"
   877  	)
   878  
   879  	var mockClient = mocks.HttpClient{}
   880  	zboxutil.Client = &mockClient
   881  
   882  	client := zclient.GetClient()
   883  	client.Wallet = &zcncrypto.Wallet{
   884  		ClientID:  mockClientId,
   885  		ClientKey: mockClientKey,
   886  	}
   887  
   888  	type parameters struct {
   889  		localPath, remotePath, contentMode string
   890  		startBlock, endBlock               int64
   891  		numBlocks                          int
   892  		statusCallback                     StatusCallback
   893  	}
   894  	tests := []struct {
   895  		name       string
   896  		parameters parameters
   897  		setup      func(*testing.T, string, parameters, *Allocation) (teardown func(*testing.T))
   898  		wantErr    bool
   899  		errMsg     string
   900  	}{
   901  		{
   902  			name: "Test_Uninitialized_Failed",
   903  			parameters: parameters{
   904  				mockLocalPath, mockRemoteFilePath,
   905  				DOWNLOAD_CONTENT_FULL,
   906  				1, 0,
   907  				numBlockDownloads,
   908  				nil,
   909  			},
   910  			setup: func(t *testing.T, testCaseName string, p parameters, a *Allocation) (teardown func(t *testing.T)) {
   911  				a.initialized = false
   912  				return func(t *testing.T) { a.initialized = true }
   913  			},
   914  			wantErr: true,
   915  			errMsg:  "sdk_not_initialized: Please call InitStorageSDK Init and use GetAllocation to get the allocation object",
   916  		},
   917  		{
   918  			name: "Test_No_Blobber_Failed",
   919  			parameters: parameters{
   920  				localPath:      mockLocalPath,
   921  				remotePath:     mockRemoteFilePath,
   922  				contentMode:    DOWNLOAD_CONTENT_FULL,
   923  				startBlock:     1,
   924  				endBlock:       0,
   925  				numBlocks:      numBlockDownloads,
   926  				statusCallback: nil,
   927  			},
   928  			setup: func(t *testing.T, testCaseName string, p parameters, a *Allocation) (teardown func(t *testing.T)) {
   929  				blobbers := a.Blobbers
   930  				a.Blobbers = []*blockchain.StorageNode{}
   931  				return func(t *testing.T) {
   932  					a.Blobbers = blobbers
   933  				}
   934  			},
   935  			wantErr: true,
   936  			errMsg:  "No Blobbers set in this allocation",
   937  		},
   938  		{
   939  			name: "Test_Download_File_Success",
   940  			parameters: parameters{
   941  				localPath:      mockLocalPath,
   942  				remotePath:     mockRemoteFilePath,
   943  				contentMode:    DOWNLOAD_CONTENT_FULL,
   944  				startBlock:     1,
   945  				endBlock:       0,
   946  				numBlocks:      numBlockDownloads,
   947  				statusCallback: nil,
   948  			},
   949  			setup: func(t *testing.T, testCaseName string, p parameters, a *Allocation) (teardown func(t *testing.T)) {
   950  				for i := 0; i < numBlobbers; i++ {
   951  					url := "TestAllocation_downloadFile" + mockBlobberUrl + strconv.Itoa(i)
   952  					mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
   953  						return strings.HasPrefix(req.URL.Path, url)
   954  					})).Return(&http.Response{
   955  						StatusCode: http.StatusOK,
   956  						Body: func() io.ReadCloser {
   957  							jsonFR, err := json.Marshal(&fileref.FileRef{
   958  								ActualFileHash: mockActualHash,
   959  							})
   960  							require.NoError(t, err)
   961  							return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
   962  						}(),
   963  					}, nil)
   964  				}
   965  				return func(t *testing.T) {
   966  					os.Remove("alloc/1.txt") //nolint: errcheck
   967  				}
   968  			},
   969  		},
   970  	}
   971  	for _, tt := range tests {
   972  		t.Run(tt.name, func(t *testing.T) {
   973  			require := require.New(t)
   974  			a := &Allocation{}
   975  			a.downloadChan = make(chan *DownloadRequest, 10)
   976  			a.repairChan = make(chan *RepairRequest, 1)
   977  			a.ctx, a.ctxCancelF = context.WithCancel(context.Background())
   978  			a.downloadProgressMap = make(map[string]*DownloadRequest)
   979  			a.mutex = &sync.Mutex{}
   980  			a.initialized = true
   981  			sdkInitialized = true
   982  			setupMockAllocation(t, a)
   983  			for i := 0; i < numBlobbers; i++ {
   984  				a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
   985  					ID:      tt.name + strconv.Itoa(i),
   986  					Baseurl: "TestAllocation_downloadFile" + tt.name + mockBlobberUrl + strconv.Itoa(i),
   987  				})
   988  			}
   989  			if m := tt.setup; m != nil {
   990  				if teardown := m(t, tt.name, tt.parameters, a); teardown != nil {
   991  					defer teardown(t)
   992  				}
   993  			}
   994  
   995  			f, localFilePath, _, err := a.prepareAndOpenLocalFile(tt.parameters.localPath, tt.parameters.remotePath)
   996  			defer func() {
   997  				f.Close()                //nolint: errcheck
   998  				os.Remove(localFilePath) //nolint: errcheck
   999  			}()
  1000  
  1001  			if err == nil {
  1002  				err = a.addAndGenerateDownloadRequest(
  1003  					f, tt.parameters.remotePath, tt.parameters.contentMode,
  1004  					tt.parameters.startBlock, tt.parameters.endBlock, tt.parameters.numBlocks,
  1005  					true, tt.parameters.statusCallback, false, localFilePath)
  1006  			}
  1007  			require.EqualValues(tt.wantErr, err != nil)
  1008  			if err != nil {
  1009  				require.EqualValues(tt.errMsg, errors.Top(err))
  1010  				return
  1011  			}
  1012  			require.NoErrorf(err, "Unexpected error: %v", err)
  1013  		})
  1014  	}
  1015  }
  1016  
  1017  func TestAllocation_GetRefs(t *testing.T) {
  1018  
  1019  	var mockClient = mocks.HttpClient{}
  1020  	zboxutil.Client = &mockClient
  1021  
  1022  	client := zclient.GetClient()
  1023  	client.Wallet = &zcncrypto.Wallet{
  1024  		ClientID:  mockClientId,
  1025  		ClientKey: mockClientKey,
  1026  	}
  1027  	functionName := "TestAllocation_GetRefs"
  1028  	t.Run("Test_Get_Refs_Returns_Slice_Of_Length_0_When_File_Not_Present", func(t *testing.T) {
  1029  		a := &Allocation{
  1030  			DataShards:   2,
  1031  			ParityShards: 2,
  1032  		}
  1033  		testCaseName := "Test_Get_Refs_Returns_Slice_Of_Length_0_When_File_Not_Present"
  1034  		a.InitAllocation()
  1035  		sdkInitialized = true
  1036  		for i := 0; i < numBlobbers; i++ {
  1037  			a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  1038  				ID:      testCaseName + mockBlobberId + strconv.Itoa(i),
  1039  				Baseurl: functionName + testCaseName + mockBlobberUrl + strconv.Itoa(i),
  1040  			})
  1041  		}
  1042  		for i := 0; i < numBlobbers; i++ {
  1043  			body, err := json.Marshal(map[string]string{
  1044  				"code":  "invalid_path",
  1045  				"error": "invalid_path: ",
  1046  			})
  1047  			require.NoError(t, err)
  1048  			setupMockHttpResponse(t, &mockClient, functionName, testCaseName, a, http.MethodGet, http.StatusBadRequest, body)
  1049  		}
  1050  		path := "/any_random_path.txt"
  1051  		otr, err := a.GetRefs(path, "", "", "", "f", "regular", 0, 5)
  1052  		require.NoError(t, err)
  1053  		require.Equal(t, true, len(otr.Refs) == 0)
  1054  
  1055  	})
  1056  }
  1057  
  1058  func TestAllocation_GetFileMeta(t *testing.T) {
  1059  	const (
  1060  		mockType       = "f"
  1061  		mockActualHash = "mockActualHash"
  1062  	)
  1063  
  1064  	var mockClient = mocks.HttpClient{}
  1065  	zboxutil.Client = &mockClient
  1066  
  1067  	client := zclient.GetClient()
  1068  	client.Wallet = &zcncrypto.Wallet{
  1069  		ClientID:  mockClientId,
  1070  		ClientKey: mockClientKey,
  1071  	}
  1072  
  1073  	type parameters struct {
  1074  		path string
  1075  	}
  1076  	tests := []struct {
  1077  		name       string
  1078  		parameters parameters
  1079  		setup      func(*testing.T, string, *Allocation) (teardown func(*testing.T))
  1080  		wantErr    bool
  1081  		errMsg     string
  1082  	}{
  1083  		{
  1084  			name:       "Test_Uninitialized_Failed",
  1085  			parameters: parameters{},
  1086  			setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) {
  1087  				a.initialized = false
  1088  				return func(t *testing.T) {
  1089  					a.initialized = true
  1090  				}
  1091  			},
  1092  			wantErr: true,
  1093  			errMsg:  "sdk_not_initialized: Please call InitStorageSDK Init and use GetAllocation to get the allocation object",
  1094  		},
  1095  		{
  1096  			name: "Test_Error_Getting_File_Meta_Data_From_Blobbers_Failed",
  1097  			parameters: parameters{
  1098  				path: "/1.txt",
  1099  			},
  1100  			setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) {
  1101  				body, err := json.Marshal(&fileref.FileRef{
  1102  					ActualFileHash: mockActualHash,
  1103  				})
  1104  				require.NoError(t, err)
  1105  				setupMockHttpResponse(t, &mockClient, "TestAllocation_GetFileMeta", testCaseName, a, http.MethodPost, http.StatusBadRequest, body)
  1106  				return nil
  1107  			},
  1108  			wantErr: true,
  1109  			errMsg:  "file_meta_error: Error getting the file meta data from blobbers",
  1110  		},
  1111  		{
  1112  			name: "Test_Success",
  1113  			parameters: parameters{
  1114  				path: "/1.txt",
  1115  			},
  1116  			setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) {
  1117  				body, err := json.Marshal(&fileref.FileRef{
  1118  					ActualFileHash: mockActualHash,
  1119  				})
  1120  				require.NoError(t, err)
  1121  				setupMockHttpResponse(t, &mockClient, "TestAllocation_GetFileMeta", testCaseName, a, http.MethodPost, http.StatusOK, body)
  1122  				return nil
  1123  			},
  1124  		},
  1125  	}
  1126  	for _, tt := range tests {
  1127  		t.Run(tt.name, func(t *testing.T) {
  1128  			require := require.New(t)
  1129  			a := &Allocation{
  1130  				DataShards:   2,
  1131  				ParityShards: 2,
  1132  				FileOptions:  63,
  1133  			}
  1134  			a.InitAllocation()
  1135  			sdkInitialized = true
  1136  			for i := 0; i < numBlobbers; i++ {
  1137  				a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  1138  					ID:      tt.name + mockBlobberId + strconv.Itoa(i),
  1139  					Baseurl: "TestAllocation_GetFileMeta" + tt.name + mockBlobberUrl + strconv.Itoa(i),
  1140  				})
  1141  			}
  1142  			if tt.setup != nil {
  1143  				if teardown := tt.setup(t, tt.name, a); teardown != nil {
  1144  					defer teardown(t)
  1145  				}
  1146  			}
  1147  			got, err := a.GetFileMeta(tt.parameters.path)
  1148  			require.EqualValues(tt.wantErr, err != nil)
  1149  			if err != nil {
  1150  				require.EqualValues(tt.errMsg, errors.Top(err))
  1151  				return
  1152  			}
  1153  			require.NoErrorf(err, "unexpected error: %v", err)
  1154  			expectedResult := &ConsolidatedFileMeta{
  1155  				Hash: mockActualHash,
  1156  			}
  1157  			require.EqualValues(expectedResult, got)
  1158  		})
  1159  	}
  1160  }
  1161  
  1162  func TestAllocation_GetAuthTicketForShare(t *testing.T) {
  1163  	const mockValidationRoot = "mock validation root"
  1164  	const numberBlobbers = 10
  1165  
  1166  	var mockClient = mocks.HttpClient{}
  1167  	httpResponse := http.Response{
  1168  		StatusCode: http.StatusOK,
  1169  		Body: func() io.ReadCloser {
  1170  			jsonFR, err := json.Marshal(fileref.FileRef{
  1171  				Ref: fileref.Ref{
  1172  					Name: mockFileRefName,
  1173  				},
  1174  				ValidationRoot: mockValidationRoot,
  1175  			})
  1176  			require.NoError(t, err)
  1177  			return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
  1178  		}(),
  1179  	}
  1180  	zboxutil.Client = &mockClient
  1181  	for i := 0; i < numBlobbers; i++ {
  1182  		mockClient.On("Do", mock.Anything).Return(&httpResponse, nil)
  1183  	}
  1184  
  1185  	client := zclient.GetClient()
  1186  	client.Wallet = &zcncrypto.Wallet{
  1187  		ClientID:  mockClientId,
  1188  		ClientKey: mockClientKey,
  1189  	}
  1190  	require := require.New(t)
  1191  	a := &Allocation{DataShards: 1, ParityShards: 1, FileOptions: 63}
  1192  	a.InitAllocation()
  1193  	for i := 0; i < numberBlobbers; i++ {
  1194  		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{})
  1195  	}
  1196  	sdkInitialized = true
  1197  	at, err := a.GetAuthTicketForShare("/1.txt", "1.txt", fileref.FILE, "")
  1198  	require.NotEmptyf(at, "unexpected empty auth ticket")
  1199  	require.NoErrorf(err, "unexpected error: %v", err)
  1200  }
  1201  
  1202  func TestAllocation_GetAuthTicket(t *testing.T) {
  1203  	var testTitle = "TestAllocation_GetAuthTicket"
  1204  	type parameters struct {
  1205  		path                       string
  1206  		filename                   string
  1207  		referenceType              string
  1208  		refereeClientID            string
  1209  		refereeEncryptionPublicKey string
  1210  	}
  1211  	tests := []struct {
  1212  		name       string
  1213  		parameters parameters
  1214  		setup      func(*testing.T, string, *Allocation, *mocks.HttpClient) (teardown func(*testing.T))
  1215  		wantErr    bool
  1216  		errMsg     string
  1217  	}{
  1218  		{
  1219  			name: "Test_Uninitialized_Failed",
  1220  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1221  				a.initialized = false
  1222  				httpResponse := http.Response{
  1223  					StatusCode: http.StatusOK,
  1224  					Body: func() io.ReadCloser {
  1225  						jsonFR, err := json.Marshal(fileref.FileRef{
  1226  							Ref: fileref.Ref{
  1227  								Name: mockFileRefName,
  1228  							},
  1229  							ValidationRoot: "mock validation root",
  1230  						})
  1231  						require.NoError(t, err)
  1232  						return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
  1233  					}(),
  1234  				}
  1235  				for i := 0; i < numBlobbers; i++ {
  1236  					mockClient.On("Do", mock.Anything).Return(&httpResponse, nil)
  1237  				}
  1238  				return func(t *testing.T) {
  1239  					a.initialized = true
  1240  				}
  1241  			},
  1242  			wantErr: true,
  1243  			errMsg:  "sdk_not_initialized: Please call InitStorageSDK Init and use GetAllocation to get the allocation object",
  1244  		},
  1245  		{
  1246  			name: "Test_Success_File_Type_Directory",
  1247  			parameters: parameters{
  1248  				path:            "/",
  1249  				filename:        "1.txt",
  1250  				referenceType:   fileref.DIRECTORY,
  1251  				refereeClientID: mockClientId,
  1252  			},
  1253  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1254  				httpResponse := &http.Response{
  1255  					StatusCode: http.StatusOK,
  1256  					Body: func() io.ReadCloser {
  1257  						jsonFR, err := json.Marshal(fileref.FileRef{
  1258  							Ref: fileref.Ref{
  1259  								Name: mockFileRefName,
  1260  							},
  1261  							ValidationRoot: "mock validation root",
  1262  						})
  1263  						require.NoError(t, err)
  1264  						return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
  1265  					}(),
  1266  				}
  1267  				for i := 0; i < numBlobbers; i++ {
  1268  					mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
  1269  						return strings.HasPrefix(req.URL.Path, testTitle+testCaseName)
  1270  					})).Return(httpResponse, nil)
  1271  				}
  1272  				return nil
  1273  			},
  1274  		},
  1275  		{
  1276  			name: "Test_Success_With_Referee_Encryption_Public_Key",
  1277  			parameters: parameters{
  1278  				path:            "/1.txt",
  1279  				filename:        "1.txt",
  1280  				referenceType:   fileref.FILE,
  1281  				refereeClientID: mockClientId,
  1282  				refereeEncryptionPublicKey: func() string {
  1283  					client_mnemonic := "travel twenty hen negative fresh sentence hen flat swift embody increase juice eternal satisfy want vessel matter honey video begin dutch trigger romance assault"
  1284  					client_encscheme := encryption.NewEncryptionScheme()
  1285  					_, err := client_encscheme.Initialize(client_mnemonic)
  1286  					require.Nil(t, err)
  1287  					client_encscheme.InitForEncryption("filetype:audio")
  1288  					client_enc_pub_key, err := client_encscheme.GetPublicKey()
  1289  					require.NoError(t, err)
  1290  					return client_enc_pub_key
  1291  				}(),
  1292  			},
  1293  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1294  				// mock GetFileMeta for private sharing validation
  1295  				fileMeta, err := json.Marshal(&fileref.FileRef{
  1296  					EncryptedKey: "EncryptedKey",
  1297  				})
  1298  				require.NoError(t, err)
  1299  				setupMockHttpResponse(t, mockClient, "TestAllocation_GetAuthTicket", testCaseName, a, http.MethodPost, http.StatusOK, fileMeta)
  1300  
  1301  				body, err := json.Marshal(&fileref.ReferencePath{
  1302  					Meta: map[string]interface{}{
  1303  						"type": "f",
  1304  					},
  1305  				})
  1306  				httpResponse := &http.Response{
  1307  					StatusCode: http.StatusOK,
  1308  					Body: func() io.ReadCloser {
  1309  						jsonFR, err := json.Marshal(fileref.FileRef{
  1310  							Ref: fileref.Ref{
  1311  								Name: mockFileRefName,
  1312  							},
  1313  							ValidationRoot: "mock validation root",
  1314  						})
  1315  						require.NoError(t, err)
  1316  						return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
  1317  					}(),
  1318  				}
  1319  				for i := 0; i < numBlobbers; i++ {
  1320  					mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
  1321  						return strings.HasPrefix(req.URL.Path, testTitle+testCaseName)
  1322  					})).Return(httpResponse, nil)
  1323  				}
  1324  				require.NoError(t, err)
  1325  				setupMockHttpResponse(t, mockClient, "TestAllocation_GetAuthTicket", testCaseName, a, http.MethodPost, http.StatusOK, body)
  1326  				return nil
  1327  			},
  1328  		},
  1329  		{
  1330  			name: "Test_Success_With_No_Referee_Encryption_Public_Key",
  1331  			parameters: parameters{
  1332  				path:                       "/1.txt",
  1333  				filename:                   "1.txt",
  1334  				referenceType:              fileref.FILE,
  1335  				refereeClientID:            mockClientId,
  1336  				refereeEncryptionPublicKey: "",
  1337  			},
  1338  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1339  
  1340  				// mock GetFileMeta for private sharing validation
  1341  				fileMeta, err := json.Marshal(&fileref.FileRef{
  1342  					EncryptedKey: "EncryptedKey",
  1343  				})
  1344  				require.NoError(t, err)
  1345  				setupMockHttpResponse(t, mockClient, "TestAllocation_GetAuthTicket", testCaseName, a, http.MethodPost, http.StatusOK, fileMeta)
  1346  
  1347  				httpResponse := &http.Response{
  1348  					StatusCode: http.StatusOK,
  1349  					Body: func() io.ReadCloser {
  1350  						jsonFR, err := json.Marshal(fileref.FileRef{
  1351  							Ref: fileref.Ref{
  1352  								Name: mockFileRefName,
  1353  							},
  1354  							ValidationRoot: "mock validation root",
  1355  						})
  1356  						require.NoError(t, err)
  1357  						return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
  1358  					}(),
  1359  				}
  1360  				for i := 0; i < numBlobbers; i++ {
  1361  					mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
  1362  						return strings.HasPrefix(req.URL.Path, testTitle+testCaseName)
  1363  					})).Return(httpResponse, nil)
  1364  				}
  1365  				return nil
  1366  			},
  1367  		},
  1368  		{
  1369  			name: "Test_Invalid_Path_Failed",
  1370  			parameters: parameters{
  1371  				filename: "1.txt",
  1372  			},
  1373  			wantErr: true,
  1374  			errMsg:  "invalid_path: Invalid path for the list",
  1375  		},
  1376  		{
  1377  			name: "Test_Remote_Path_Not_Absolute_Failed",
  1378  			parameters: parameters{
  1379  				path: "x",
  1380  			},
  1381  			wantErr: true,
  1382  			errMsg:  "invalid_path: Path should be valid and absolute",
  1383  		},
  1384  	}
  1385  
  1386  	for _, tt := range tests {
  1387  		t.Run(tt.name, func(t *testing.T) {
  1388  			var mockClient = mocks.HttpClient{}
  1389  			zboxutil.Client = &mockClient
  1390  
  1391  			client := zclient.GetClient()
  1392  			client.Wallet = &zcncrypto.Wallet{
  1393  				ClientID:  mockClientId,
  1394  				ClientKey: mockClientKey,
  1395  			}
  1396  
  1397  			require := require.New(t)
  1398  			a := &Allocation{
  1399  				DataShards:   1,
  1400  				ParityShards: 1,
  1401  				FileOptions:  63,
  1402  			}
  1403  			a.InitAllocation()
  1404  			sdkInitialized = true
  1405  
  1406  			for i := 0; i < numBlobbers; i++ {
  1407  				a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  1408  					ID:      tt.name + mockBlobberId + strconv.Itoa(i),
  1409  					Baseurl: "TestAllocation_GetAuthTicket" + tt.name + mockBlobberUrl + strconv.Itoa(i),
  1410  				})
  1411  			}
  1412  
  1413  			zboxutil.Client = &mockClient
  1414  
  1415  			if tt.setup != nil {
  1416  				if teardown := tt.setup(t, tt.name, a, &mockClient); teardown != nil {
  1417  					defer teardown(t)
  1418  				}
  1419  			}
  1420  			at, err := a.GetAuthTicket(tt.parameters.path, tt.parameters.filename, tt.parameters.referenceType, tt.parameters.refereeClientID, tt.parameters.refereeEncryptionPublicKey, 0, nil)
  1421  			require.EqualValues(tt.wantErr, err != nil, errors.Top(err))
  1422  			if err != nil {
  1423  				require.EqualValues(tt.errMsg, errors.Top(err))
  1424  				return
  1425  			}
  1426  			require.NoErrorf(err, "unexpected error: %v", err)
  1427  			require.NotEmptyf(at, "unexpected empty auth ticket")
  1428  		})
  1429  	}
  1430  }
  1431  
  1432  func TestAllocation_CancelDownload(t *testing.T) {
  1433  	const remotePath = "/1.txt"
  1434  	type parameters struct {
  1435  		remotepath string
  1436  	}
  1437  	tests := []struct {
  1438  		name       string
  1439  		parameters parameters
  1440  		setup      func(*testing.T, *Allocation) (teardown func(*testing.T))
  1441  		wantErr    bool
  1442  		errMsg     string
  1443  	}{
  1444  		{
  1445  			name:    "Test_Failed",
  1446  			wantErr: true,
  1447  			errMsg:  "local_path_not_found: Invalid path. No upload in progress for the path",
  1448  		},
  1449  		{
  1450  			name: "Test_Success",
  1451  			parameters: parameters{
  1452  				remotepath: remotePath,
  1453  			},
  1454  			setup: func(t *testing.T, a *Allocation) (teardown func(t *testing.T)) {
  1455  				req := &DownloadRequest{}
  1456  				req.ctx, req.ctxCncl = context.WithCancel(context.TODO())
  1457  				a.downloadProgressMap[remotePath] = req
  1458  				return nil
  1459  			},
  1460  		},
  1461  	}
  1462  	for _, tt := range tests {
  1463  		t.Run(tt.name, func(t *testing.T) {
  1464  			require := require.New(t)
  1465  			a := &Allocation{FileOptions: 63}
  1466  			a.InitAllocation()
  1467  			sdkInitialized = true
  1468  			if tt.setup != nil {
  1469  				if teardown := tt.setup(t, a); teardown != nil {
  1470  					defer teardown(t)
  1471  				}
  1472  			}
  1473  			err := a.CancelDownload(tt.parameters.remotepath)
  1474  			if tt.wantErr {
  1475  				require.Error(err, "expected error != nil")
  1476  				return
  1477  			}
  1478  			require.NoErrorf(err, "unexpected error: %v", err)
  1479  		})
  1480  	}
  1481  }
  1482  
  1483  func TestAllocation_ListDirFromAuthTicket(t *testing.T) {
  1484  	const (
  1485  		mockLookupHash = "mock lookup hash"
  1486  		mockType       = "d"
  1487  	)
  1488  
  1489  	authTicket := getMockAuthTicket(t)
  1490  
  1491  	type parameters struct {
  1492  		authTicket     string
  1493  		lookupHash     string
  1494  		expectedResult *ListResult
  1495  	}
  1496  	tests := []struct {
  1497  		name       string
  1498  		parameters parameters
  1499  		setup      func(*testing.T, string, *Allocation, *mocks.HttpClient) (teardown func(t *testing.T))
  1500  		wantErr    bool
  1501  		errMsg     string
  1502  	}{
  1503  		{
  1504  			name: "Test_Uninitialized_Failed",
  1505  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1506  				a.initialized = false
  1507  				return func(t *testing.T) {
  1508  					a.initialized = true
  1509  				}
  1510  			},
  1511  			wantErr: true,
  1512  			errMsg:  "invalid_path: Invalid path for the list",
  1513  		},
  1514  		{
  1515  			name: "Test_Cannot_Decode_Auth_Ticket_Failed",
  1516  			parameters: parameters{
  1517  				authTicket: "some wrong auth ticket to decode",
  1518  			},
  1519  			setup:   nil,
  1520  			wantErr: true,
  1521  			errMsg: "invalid_path: Invalid path for the list" +
  1522  				"",
  1523  		},
  1524  		{
  1525  			name: "Test_Cannot_Unmarshal_Auth_Ticket_Failed",
  1526  			parameters: parameters{
  1527  				authTicket: "c29tZSB3cm9uZyBhdXRoIHRpY2tldCB0byBtYXJzaGFs",
  1528  			},
  1529  			setup:   nil,
  1530  			wantErr: true,
  1531  			errMsg:  "invalid_path: Invalid path for the list",
  1532  		},
  1533  		{
  1534  			name: "Test_Wrong_Auth_Ticket_File_Path_Hash_Or_Lookup_Hash_Failed",
  1535  			parameters: parameters{
  1536  				authTicket: authTicket,
  1537  				lookupHash: "",
  1538  			},
  1539  			setup:   nil,
  1540  			wantErr: true,
  1541  			errMsg:  "invalid_path: Invalid path for the list",
  1542  		},
  1543  		{
  1544  			name: "Test_Error_Get_List_File_From_Blobbers_Failed",
  1545  			parameters: parameters{
  1546  				authTicket:     authTicket,
  1547  				lookupHash:     mockLookupHash,
  1548  				expectedResult: &ListResult{},
  1549  			},
  1550  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1551  				for i := 0; i < numBlobbers; i++ {
  1552  					a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  1553  						Baseurl: "TestAllocation_ListDirFromAuthTicket" + testCaseName + mockBlobberUrl + strconv.Itoa(i),
  1554  					})
  1555  				}
  1556  
  1557  				setupMockHttpResponse(t, mockClient, "TestAllocation_ListDirFromAuthTicket", testCaseName, a, http.MethodGet, http.StatusBadRequest, []byte(""))
  1558  				return func(t *testing.T) {
  1559  					a.Blobbers = nil
  1560  				}
  1561  			},
  1562  			wantErr: true,
  1563  			errMsg:  "error from server list response: ",
  1564  		},
  1565  		{
  1566  			name: "Test_Success",
  1567  			parameters: parameters{
  1568  				authTicket: authTicket,
  1569  				lookupHash: mockLookupHash,
  1570  				expectedResult: &ListResult{
  1571  					Type: mockType,
  1572  					Size: 0,
  1573  				},
  1574  			},
  1575  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1576  				for i := 0; i < numBlobbers; i++ {
  1577  					a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  1578  						ID:      testCaseName + mockBlobberId + strconv.Itoa(i),
  1579  						Baseurl: "TestAllocation_ListDirFromAuthTicket" + testCaseName + mockBlobberUrl + strconv.Itoa(i),
  1580  					})
  1581  				}
  1582  				body, err := json.Marshal(&fileref.ListResult{
  1583  					AllocationRoot: mockAllocationRoot,
  1584  					Meta: map[string]interface{}{
  1585  						"type": mockType,
  1586  					},
  1587  				})
  1588  				require.NoError(t, err)
  1589  				setupMockHttpResponse(t, mockClient, "TestAllocation_ListDirFromAuthTicket", testCaseName, a, http.MethodGet, http.StatusOK, body)
  1590  				return nil
  1591  			},
  1592  		},
  1593  	}
  1594  	for _, tt := range tests {
  1595  		t.Run(tt.name, func(t *testing.T) {
  1596  			require := require.New(t)
  1597  
  1598  			var mockClient = mocks.HttpClient{}
  1599  			zboxutil.Client = &mockClient
  1600  
  1601  			client := zclient.GetClient()
  1602  			client.Wallet = &zcncrypto.Wallet{
  1603  				ClientID:  mockClientId,
  1604  				ClientKey: mockClientKey,
  1605  			}
  1606  			a := &Allocation{
  1607  				ID:           mockAllocationId,
  1608  				Tx:           mockAllocationTxId,
  1609  				FileOptions:  63,
  1610  				DataShards:   2,
  1611  				ParityShards: 2,
  1612  			}
  1613  			if tt.parameters.expectedResult != nil {
  1614  				tt.parameters.expectedResult.deleteMask = zboxutil.NewUint128(1).Lsh(uint64(a.DataShards + a.ParityShards)).Sub64(1)
  1615  			}
  1616  			if tt.setup != nil {
  1617  				if teardown := tt.setup(t, tt.name, a, &mockClient); teardown != nil {
  1618  					defer teardown(t)
  1619  				}
  1620  			}
  1621  
  1622  			setupMockGetFileInfoResponse(t, &mockClient)
  1623  			a.InitAllocation()
  1624  			sdkInitialized = true
  1625  			if len(a.Blobbers) == 0 {
  1626  				for i := 0; i < numBlobbers; i++ {
  1627  					a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{})
  1628  				}
  1629  			}
  1630  
  1631  			got, err := a.ListDirFromAuthTicket(authTicket, tt.parameters.lookupHash)
  1632  			require.EqualValues(tt.wantErr, err != nil)
  1633  			if err != nil {
  1634  				require.EqualValues(tt.errMsg, errors.Top(err))
  1635  				return
  1636  			}
  1637  			require.NoErrorf(err, "unexpected error: %v", err)
  1638  			require.EqualValues(tt.parameters.expectedResult, got)
  1639  		})
  1640  	}
  1641  }
  1642  
  1643  func TestAllocation_downloadFromAuthTicket(t *testing.T) {
  1644  	const (
  1645  		mockLookupHash     = "mock lookup hash"
  1646  		mockLocalPath      = "alloc"
  1647  		mockRemoteFileName = "1.txt"
  1648  		mockType           = "f"
  1649  		mockActualHash     = "mockActualHash"
  1650  	)
  1651  
  1652  	var mockClient = mocks.HttpClient{}
  1653  	zboxutil.Client = &mockClient
  1654  
  1655  	client := zclient.GetClient()
  1656  	client.Wallet = &zcncrypto.Wallet{
  1657  		ClientID:  mockClientId,
  1658  		ClientKey: mockClientKey,
  1659  	}
  1660  
  1661  	a := &Allocation{
  1662  		ID:           mockAllocationId,
  1663  		Tx:           mockAllocationTxId,
  1664  		DataShards:   2,
  1665  		ParityShards: 2,
  1666  	}
  1667  	setupMockAllocation(t, a)
  1668  	setupMockGetFileInfoResponse(t, &mockClient)
  1669  	authTicket := getMockAuthTicket(t)
  1670  
  1671  	type parameters struct {
  1672  		localPath      string
  1673  		authTicket     string
  1674  		lookupHash     string
  1675  		startBlock     int64
  1676  		endBlock       int64
  1677  		numBlocks      int
  1678  		remoteFilename string
  1679  		contentMode    string
  1680  		statusCallback StatusCallback
  1681  	}
  1682  	tests := []struct {
  1683  		name                      string
  1684  		parameters                parameters
  1685  		setup                     func(*testing.T, string, parameters) (teardown func(*testing.T))
  1686  		blockDownloadResponseMock func(blobber *blockchain.StorageNode, wg *sync.WaitGroup)
  1687  		wantErr                   bool
  1688  		errMsg                    string
  1689  	}{
  1690  		{
  1691  			name: "Test_Uninitialized_Failed",
  1692  			setup: func(t *testing.T, testCaseName string, p parameters) (teardown func(t *testing.T)) {
  1693  				a.initialized = false
  1694  				return func(t *testing.T) {
  1695  					a.initialized = true
  1696  				}
  1697  			},
  1698  			wantErr: true,
  1699  			errMsg:  "sdk_not_initialized: Please call InitStorageSDK Init and use GetAllocation to get the allocation object",
  1700  		},
  1701  		{
  1702  			name: "Test_Cannot_Decode_Auth_Ticket_Failed",
  1703  			parameters: parameters{
  1704  				localPath:      mockLocalPath,
  1705  				authTicket:     "some wrong auth ticket to decode",
  1706  				remoteFilename: mockRemoteFileName,
  1707  			},
  1708  			wantErr: true,
  1709  			errMsg:  "auth_ticket_decode_error: Error decoding the auth ticket.illegal base64 data at input byte 4",
  1710  		},
  1711  		{
  1712  			name: "Test_Cannot_Unmarshal_Auth_Ticket_Failed",
  1713  			parameters: parameters{
  1714  				localPath:      mockLocalPath,
  1715  				authTicket:     "c29tZSB3cm9uZyBhdXRoIHRpY2tldCB0byBtYXJzaGFs",
  1716  				remoteFilename: mockRemoteFileName,
  1717  			},
  1718  			wantErr: true,
  1719  			errMsg:  "auth_ticket_decode_error: Error unmarshaling the auth ticket.invalid character 's' looking for beginning of value",
  1720  		},
  1721  		{
  1722  			name: "Test_Not_Enough_Minimum_Blobbers_Failed",
  1723  			parameters: parameters{
  1724  				localPath:      mockLocalPath,
  1725  				authTicket:     authTicket,
  1726  				remoteFilename: mockRemoteFileName,
  1727  			},
  1728  			setup: func(t *testing.T, testCaseName string, p parameters) (teardown func(t *testing.T)) {
  1729  				blobbers := a.Blobbers
  1730  				a.Blobbers = []*blockchain.StorageNode{}
  1731  				return func(t *testing.T) {
  1732  					a.Blobbers = blobbers
  1733  				}
  1734  			},
  1735  			wantErr: true,
  1736  			errMsg:  "No Blobbers set in this allocation",
  1737  		},
  1738  		{
  1739  			name: "Test_Download_File_Success",
  1740  			parameters: parameters{
  1741  				localPath:      mockLocalPath,
  1742  				remoteFilename: mockRemoteFileName,
  1743  				authTicket:     authTicket,
  1744  				contentMode:    DOWNLOAD_CONTENT_FULL,
  1745  				startBlock:     1,
  1746  				endBlock:       0,
  1747  				numBlocks:      numBlockDownloads,
  1748  				lookupHash:     mockLookupHash},
  1749  			setup: func(t *testing.T, testCaseName string, p parameters) (teardown func(t *testing.T)) {
  1750  				for i := 0; i < numBlobbers; i++ {
  1751  					a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  1752  						ID:      testCaseName + mockBlobberId + strconv.Itoa(i),
  1753  						Baseurl: "TestAllocation_downloadFromAuthTicket" + testCaseName + mockBlobberUrl + strconv.Itoa(i),
  1754  					})
  1755  				}
  1756  				body, err := json.Marshal(&fileref.FileRef{
  1757  					Ref: fileref.Ref{
  1758  						Name: mockFileRefName,
  1759  					},
  1760  				})
  1761  				require.NoError(t, err)
  1762  				setupMockHttpResponse(t, &mockClient, "TestAllocation_downloadFromAuthTicket", testCaseName, a, http.MethodPost, http.StatusOK, body)
  1763  				return nil
  1764  			},
  1765  		},
  1766  	}
  1767  	for _, tt := range tests {
  1768  		t.Run(tt.name, func(t *testing.T) {
  1769  			require := require.New(t)
  1770  			if tt.setup != nil {
  1771  				if teardown := tt.setup(t, tt.name, tt.parameters); teardown != nil {
  1772  					defer teardown(t)
  1773  				}
  1774  			}
  1775  
  1776  			f, localFilePath, _, err := a.prepareAndOpenLocalFile(tt.parameters.localPath, tt.parameters.remoteFilename)
  1777  			defer func() {
  1778  				f.Close()                   //nolint: errcheck
  1779  				os.RemoveAll(mockLocalPath) //nolint: errcheck
  1780  			}()
  1781  
  1782  			if err == nil {
  1783  				err = a.downloadFromAuthTicket(
  1784  					f, tt.parameters.authTicket, tt.parameters.lookupHash,
  1785  					tt.parameters.startBlock, tt.parameters.endBlock, tt.parameters.numBlocks,
  1786  					tt.parameters.remoteFilename, tt.parameters.contentMode, true, tt.parameters.statusCallback, false, localFilePath)
  1787  			}
  1788  
  1789  			require.EqualValues(tt.wantErr, err != nil)
  1790  			if err != nil {
  1791  				require.EqualValues(tt.errMsg, errors.Top(err))
  1792  				return
  1793  			}
  1794  			require.NoErrorf(err, "unexpected error: %v", err)
  1795  		})
  1796  	}
  1797  }
  1798  
  1799  func TestAllocation_listDir(t *testing.T) {
  1800  	const (
  1801  		mockPath = "/1.txt"
  1802  		mockType = "d"
  1803  	)
  1804  
  1805  	type parameters struct {
  1806  		path           string
  1807  		expectedResult *ListResult
  1808  	}
  1809  	tests := []struct {
  1810  		name       string
  1811  		parameters parameters
  1812  		setup      func(*testing.T, string, *Allocation, *mocks.HttpClient) (teardown func(*testing.T))
  1813  		wantErr    bool
  1814  		errMsg     string
  1815  	}{
  1816  		{
  1817  			name: "Test_Uninitialized_Failed",
  1818  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1819  				a.initialized = false
  1820  				return func(t *testing.T) {
  1821  					a.initialized = true
  1822  				}
  1823  			},
  1824  			wantErr: true,
  1825  			errMsg:  "sdk_not_initialized: Please call InitStorageSDK Init and use GetAllocation to get the allocation object",
  1826  		},
  1827  		{
  1828  			name:    "Test_Invalid_Path_Failed",
  1829  			wantErr: true,
  1830  			errMsg:  "invalid_path: Invalid path for the list",
  1831  		},
  1832  		{
  1833  			name: "Test_Invalid_Absolute_Path_Failed",
  1834  			parameters: parameters{
  1835  				path: "1.txt",
  1836  			},
  1837  			wantErr: true,
  1838  			errMsg:  "invalid_path: Path should be valid and absolute",
  1839  		},
  1840  		{
  1841  			name: "Test_Error_Get_List_File_From_Blobbers_Failed",
  1842  			parameters: parameters{
  1843  				path:           mockPath,
  1844  				expectedResult: &ListResult{},
  1845  			},
  1846  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1847  				setupMockHttpResponse(t, mockClient, "TestAllocation_listDir", testCaseName, a, http.MethodGet, http.StatusBadRequest, []byte(""))
  1848  				return nil
  1849  			},
  1850  			wantErr: true,
  1851  			errMsg:  "error from server list response: ",
  1852  		},
  1853  		{
  1854  			name: "Test_Success",
  1855  			parameters: parameters{
  1856  				path: mockPath,
  1857  				expectedResult: &ListResult{
  1858  					Type: mockType,
  1859  					Size: 0,
  1860  				},
  1861  			},
  1862  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1863  				body, err := json.Marshal(&fileref.ListResult{
  1864  					AllocationRoot: mockAllocationRoot,
  1865  					Meta: map[string]interface{}{
  1866  						"type": mockType,
  1867  					},
  1868  				})
  1869  				require.NoError(t, err)
  1870  				setupMockHttpResponse(t, mockClient, "TestAllocation_listDir", testCaseName, a, http.MethodGet, http.StatusOK, body)
  1871  				return nil
  1872  			},
  1873  		},
  1874  	}
  1875  
  1876  	for _, tt := range tests {
  1877  		t.Run(tt.name, func(t *testing.T) {
  1878  			var mockClient = mocks.HttpClient{}
  1879  			zboxutil.Client = &mockClient
  1880  
  1881  			client := zclient.GetClient()
  1882  			client.Wallet = &zcncrypto.Wallet{
  1883  				ClientID:  mockClientId,
  1884  				ClientKey: mockClientKey,
  1885  			}
  1886  
  1887  			require := require.New(t)
  1888  			a := &Allocation{
  1889  				ID:           mockAllocationId,
  1890  				Tx:           mockAllocationTxId,
  1891  				FileOptions:  63,
  1892  				DataShards:   2,
  1893  				ParityShards: 2,
  1894  			}
  1895  			if tt.parameters.expectedResult != nil {
  1896  				tt.parameters.expectedResult.deleteMask = zboxutil.NewUint128(1).Lsh(uint64(a.DataShards + a.ParityShards)).Sub64(1)
  1897  			}
  1898  			a.InitAllocation()
  1899  			sdkInitialized = true
  1900  			for i := 0; i < numBlobbers; i++ {
  1901  				a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  1902  					ID:      tt.name + mockBlobberId + strconv.Itoa(i),
  1903  					Baseurl: "TestAllocation_listDir" + tt.name + mockBlobberUrl + strconv.Itoa(i),
  1904  				})
  1905  			}
  1906  			if tt.setup != nil {
  1907  				if teardown := tt.setup(t, tt.name, a, &mockClient); teardown != nil {
  1908  					defer teardown(t)
  1909  				}
  1910  			}
  1911  			got, err := a.ListDir(tt.parameters.path)
  1912  			require.EqualValues(tt.wantErr, err != nil)
  1913  			if err != nil {
  1914  				require.EqualValues(tt.errMsg, errors.Top(err))
  1915  				return
  1916  			}
  1917  			require.NoErrorf(err, "unexpected error: %v", err)
  1918  			require.EqualValues(tt.parameters.expectedResult, got)
  1919  		})
  1920  	}
  1921  }
  1922  
  1923  func TestAllocation_GetFileMetaFromAuthTicket(t *testing.T) {
  1924  	const (
  1925  		mockLookupHash = "mock lookup hash"
  1926  		mockActualHash = "mockActualHash"
  1927  		mockType       = "f"
  1928  	)
  1929  
  1930  	var authTicket = getMockAuthTicket(t)
  1931  
  1932  	type parameters struct {
  1933  		authTicket, lookupHash string
  1934  	}
  1935  	tests := []struct {
  1936  		name       string
  1937  		parameters parameters
  1938  		setup      func(*testing.T, string, *Allocation, *mocks.HttpClient) (teardown func(t *testing.T))
  1939  		wantErr    bool
  1940  		errMsg     string
  1941  	}{
  1942  		{
  1943  			name: "Test_Uninitialized_Failed",
  1944  			setup: func(t *testing.T, testCaseName string, a *Allocation, _ *mocks.HttpClient) (teardown func(t *testing.T)) {
  1945  				a.initialized = false
  1946  				return func(t *testing.T) {
  1947  					a.initialized = true
  1948  				}
  1949  			},
  1950  			wantErr: true,
  1951  			errMsg:  "sdk_not_initialized: Please call InitStorageSDK Init and use GetAllocation to get the allocation object",
  1952  		},
  1953  		{
  1954  			name: "Test_Cannot_Decode_Auth_Ticket_Failed",
  1955  			parameters: parameters{
  1956  				authTicket: "some wrong auth ticket to decode",
  1957  			},
  1958  			wantErr: true,
  1959  			errMsg:  "auth_ticket_decode_error: Error decoding the auth ticket.illegal base64 data at input byte 4",
  1960  		},
  1961  		{
  1962  			name: "Test_Cannot_Unmarshal_Auth_Ticket_Failed",
  1963  			parameters: parameters{
  1964  				authTicket: "c29tZSB3cm9uZyBhdXRoIHRpY2tldCB0byBtYXJzaGFs",
  1965  			},
  1966  			wantErr: true,
  1967  			errMsg:  "auth_ticket_decode_error: Error unmarshaling the auth ticket.invalid character 's' looking for beginning of value",
  1968  		},
  1969  		{
  1970  			name: "Test_Wrong_Auth_Ticket_File_Path_Hash_Or_Lookup_Hash_Failed",
  1971  			parameters: parameters{
  1972  				authTicket: authTicket,
  1973  				lookupHash: "",
  1974  			},
  1975  			wantErr: true,
  1976  			errMsg:  "invalid_path: Invalid path for the list",
  1977  		},
  1978  		{
  1979  			name: "Test_Error_Get_File_Meta_From_Blobbers_Failed",
  1980  			parameters: parameters{
  1981  				authTicket: authTicket,
  1982  				lookupHash: mockLookupHash,
  1983  			},
  1984  			wantErr: true,
  1985  			errMsg:  "file_meta_error: Error getting the file meta data from blobbers",
  1986  		},
  1987  		{
  1988  			name: "Test_Success",
  1989  			parameters: parameters{
  1990  				authTicket: authTicket,
  1991  				lookupHash: mockLookupHash,
  1992  			},
  1993  			setup: func(t *testing.T, testCaseName string, a *Allocation, mockClient *mocks.HttpClient) (teardown func(t *testing.T)) {
  1994  				for i := 0; i < numBlobbers; i++ {
  1995  					a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  1996  						ID:      testCaseName + mockBlobberId + strconv.Itoa(i),
  1997  						Baseurl: "TestAllocation_GetFileMetaFromAuthTicket" + testCaseName + mockBlobberUrl + strconv.Itoa(i),
  1998  					})
  1999  				}
  2000  				body, err := json.Marshal(&fileref.FileRef{
  2001  					ActualFileHash: mockActualHash,
  2002  				})
  2003  				require.NoError(t, err)
  2004  				setupMockHttpResponse(t, mockClient, "TestAllocation_GetFileMetaFromAuthTicket", testCaseName, a, http.MethodPost, http.StatusOK, body)
  2005  				return nil
  2006  			},
  2007  		},
  2008  	}
  2009  
  2010  	for _, tt := range tests {
  2011  		t.Run(tt.name, func(t *testing.T) {
  2012  			var mockClient = mocks.HttpClient{}
  2013  			zboxutil.Client = &mockClient
  2014  
  2015  			client := zclient.GetClient()
  2016  			client.Wallet = &zcncrypto.Wallet{
  2017  				ClientID:  mockClientId,
  2018  				ClientKey: mockClientKey,
  2019  			}
  2020  
  2021  			a := &Allocation{
  2022  				ID:           mockAllocationId,
  2023  				Tx:           mockAllocationTxId,
  2024  				DataShards:   2,
  2025  				ParityShards: 2,
  2026  				FileOptions:  63,
  2027  			}
  2028  			a.InitAllocation()
  2029  			sdkInitialized = true
  2030  			a.initialized = true
  2031  
  2032  			require := require.New(t)
  2033  			if tt.setup != nil {
  2034  				if teardown := tt.setup(t, tt.name, a, &mockClient); teardown != nil {
  2035  					defer teardown(t)
  2036  				}
  2037  			}
  2038  			got, err := a.GetFileMetaFromAuthTicket(tt.parameters.authTicket, tt.parameters.lookupHash)
  2039  			require.EqualValues(tt.wantErr, err != nil)
  2040  			if err != nil {
  2041  				require.EqualValues(tt.errMsg, errors.Top(err))
  2042  				return
  2043  			}
  2044  			require.NoErrorf(err, "unexpected error: %v", err)
  2045  			expectedResult := &ConsolidatedFileMeta{
  2046  				Hash: mockActualHash,
  2047  			}
  2048  			require.EqualValues(expectedResult, got)
  2049  		})
  2050  	}
  2051  }
  2052  
  2053  func TestAllocation_DownloadToFileHandlerFromAuthTicket(t *testing.T) {
  2054  	const (
  2055  		mockLookupHash     = "mock lookup hash"
  2056  		mockRemoteFilePath = "1.txt"
  2057  		mockType           = "d"
  2058  	)
  2059  
  2060  	var mockFile = &sys.MemFile{Name: "mockFile", Mode: fs.ModePerm, ModTime: time.Now()}
  2061  	var mockClient = mocks.HttpClient{}
  2062  	zboxutil.Client = &mockClient
  2063  
  2064  	client := zclient.GetClient()
  2065  	client.Wallet = &zcncrypto.Wallet{
  2066  		ClientID:  mockClientId,
  2067  		ClientKey: mockClientKey,
  2068  	}
  2069  
  2070  	require := require.New(t)
  2071  
  2072  	a := &Allocation{}
  2073  	setupMockAllocation(t, a)
  2074  	for i := 0; i < numBlobbers; i++ {
  2075  		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  2076  			ID:      strconv.Itoa(i),
  2077  			Baseurl: "TestAllocation_DownloadFromAuthTicket" + mockBlobberUrl + strconv.Itoa(i),
  2078  		})
  2079  	}
  2080  
  2081  	var authTicket = getMockAuthTicket(t)
  2082  
  2083  	err := a.DownloadFileToFileHandlerFromAuthTicket(mockFile, authTicket, mockLookupHash,
  2084  		mockRemoteFilePath, false, nil, false)
  2085  	defer os.Remove("alloc/1.txt")
  2086  	require.NoErrorf(err, "unexpected error: %v", err)
  2087  }
  2088  
  2089  func TestAllocation_DownloadThumbnailFromAuthTicket(t *testing.T) {
  2090  	const (
  2091  		mockLookupHash     = "mock lookup hash"
  2092  		mockLocalPath      = "alloc"
  2093  		mockRemoteFilePath = "1.txt"
  2094  		mockType           = "d"
  2095  	)
  2096  
  2097  	var mockClient = mocks.HttpClient{}
  2098  	zboxutil.Client = &mockClient
  2099  
  2100  	client := zclient.GetClient()
  2101  	client.Wallet = &zcncrypto.Wallet{
  2102  		ClientID:  mockClientId,
  2103  		ClientKey: mockClientKey,
  2104  	}
  2105  
  2106  	require := require.New(t)
  2107  
  2108  	a := &Allocation{}
  2109  	setupMockAllocation(t, a)
  2110  	for i := 0; i < numBlobbers; i++ {
  2111  		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  2112  			ID:      strconv.Itoa(i),
  2113  			Baseurl: "TestAllocation_DownloadThumbnailFromAuthTicket" + mockBlobberUrl + strconv.Itoa(i),
  2114  		})
  2115  	}
  2116  
  2117  	var authTicket = getMockAuthTicket(t)
  2118  
  2119  	body, err := json.Marshal(&fileref.ReferencePath{
  2120  		Meta: map[string]interface{}{
  2121  			"type": mockType,
  2122  		},
  2123  	})
  2124  	require.NoError(err)
  2125  	setupMockHttpResponse(t, &mockClient, "TestAllocation_DownloadThumbnailFromAuthTicket", "", a, http.MethodGet, http.StatusOK, body)
  2126  
  2127  	err = a.DownloadThumbnailFromAuthTicket(mockLocalPath, authTicket, mockLookupHash, mockRemoteFilePath, true, nil, false)
  2128  	defer os.Remove("alloc/1.txt")
  2129  	require.NoErrorf(err, "unexpected error: %v", err)
  2130  }
  2131  
  2132  func TestAllocation_DownloadFromAuthTicket(t *testing.T) {
  2133  	const (
  2134  		mockLookupHash     = "mock lookup hash"
  2135  		mockLocalPath      = "alloc"
  2136  		mockRemoteFilePath = "1.txt"
  2137  		mockType           = "d"
  2138  	)
  2139  
  2140  	var mockClient = mocks.HttpClient{}
  2141  	zboxutil.Client = &mockClient
  2142  
  2143  	client := zclient.GetClient()
  2144  	client.Wallet = &zcncrypto.Wallet{
  2145  		ClientID:  mockClientId,
  2146  		ClientKey: mockClientKey,
  2147  	}
  2148  
  2149  	require := require.New(t)
  2150  
  2151  	a := &Allocation{}
  2152  	setupMockAllocation(t, a)
  2153  	for i := 0; i < numBlobbers; i++ {
  2154  		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  2155  			ID:      strconv.Itoa(i),
  2156  			Baseurl: "TestAllocation_DownloadFromAuthTicket" + mockBlobberUrl + strconv.Itoa(i),
  2157  		})
  2158  	}
  2159  
  2160  	var authTicket = getMockAuthTicket(t)
  2161  
  2162  	err := a.DownloadFromAuthTicket(mockLocalPath, authTicket, mockLookupHash, mockRemoteFilePath, true, nil, false)
  2163  	defer os.Remove("alloc/1.txt")
  2164  	require.NoErrorf(err, "unexpected error: %v", err)
  2165  }
  2166  
  2167  func TestAllocation_DownloadFromAuthTicketByBlocks(t *testing.T) {
  2168  	const (
  2169  		mockLookupHash     = "mock lookup hash"
  2170  		mockLocalPath      = "alloc"
  2171  		mockRemoteFilePath = "1.txt"
  2172  		mockType           = "d"
  2173  	)
  2174  
  2175  	var authTicket = getMockAuthTicket(t)
  2176  
  2177  	var mockClient = mocks.HttpClient{}
  2178  	zboxutil.Client = &mockClient
  2179  
  2180  	client := zclient.GetClient()
  2181  	client.Wallet = &zcncrypto.Wallet{
  2182  		ClientID:  mockClientId,
  2183  		ClientKey: mockClientKey,
  2184  	}
  2185  
  2186  	require := require.New(t)
  2187  
  2188  	a := &Allocation{}
  2189  	setupMockAllocation(t, a)
  2190  	for i := 0; i < numBlobbers; i++ {
  2191  		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  2192  			ID:      strconv.Itoa(i),
  2193  			Baseurl: "TestAllocation_DownloadFromAuthTicketByBlocks" + mockBlobberUrl + strconv.Itoa(i),
  2194  		})
  2195  	}
  2196  
  2197  	setupMockHttpResponse(t, &mockClient, "TestAllocation_DownloadFromAuthTicketByBlocks", "", a, http.MethodPost, http.StatusBadRequest, []byte(""))
  2198  
  2199  	err := a.DownloadFromAuthTicketByBlocks(
  2200  		mockLocalPath, authTicket, 1, 0, numBlockDownloads, mockLookupHash, mockRemoteFilePath, true, nil, false)
  2201  	defer os.Remove("alloc/1.txt")
  2202  	require.NoErrorf(err, "unexpected error: %v", err)
  2203  }
  2204  
  2205  func TestAllocation_StartRepair(t *testing.T) {
  2206  	const (
  2207  		mockLookupHash   = "mock lookup hash"
  2208  		mockLocalPath    = "alloc"
  2209  		mockPathToRepair = "/1.txt"
  2210  		mockType         = "d"
  2211  	)
  2212  
  2213  	var mockClient = mocks.HttpClient{}
  2214  	zboxutil.Client = &mockClient
  2215  
  2216  	client := zclient.GetClient()
  2217  	client.Wallet = &zcncrypto.Wallet{
  2218  		ClientID:  mockClientId,
  2219  		ClientKey: mockClientKey,
  2220  	}
  2221  
  2222  	type parameters struct {
  2223  		localPath, pathToRepair string
  2224  		statusCallback          StatusCallback
  2225  	}
  2226  	tests := []struct {
  2227  		name       string
  2228  		parameters parameters
  2229  		setup      func(*testing.T, string, *Allocation) (teardown func(*testing.T))
  2230  		wantErr    bool
  2231  		errMsg     string
  2232  	}{
  2233  		{
  2234  			name: "Test_Uninitialized_Failed",
  2235  			setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) {
  2236  				a.initialized = false
  2237  				return func(t *testing.T) {
  2238  					a.initialized = true
  2239  				}
  2240  			},
  2241  			wantErr: true,
  2242  			errMsg:  "sdk_not_initialized: Please call InitStorageSDK Init and use GetAllocation to get the allocation object",
  2243  		},
  2244  		{
  2245  			name: "Test_Repair_Success",
  2246  			parameters: parameters{
  2247  				localPath:    mockLocalPath,
  2248  				pathToRepair: "/1.txt",
  2249  			},
  2250  			setup: func(t *testing.T, testCaseName string, a *Allocation) (teardown func(t *testing.T)) {
  2251  				body, err := json.Marshal(&fileref.ListResult{
  2252  					AllocationRoot: mockAllocationRoot,
  2253  					Meta: map[string]interface{}{
  2254  						"type": mockType,
  2255  					},
  2256  				})
  2257  				require.NoError(t, err)
  2258  				setupMockHttpResponse(t, &mockClient, "TestAllocation_StartRepair", testCaseName, a, http.MethodGet, http.StatusOK, body)
  2259  				return nil
  2260  			},
  2261  		},
  2262  	}
  2263  	for _, tt := range tests {
  2264  		t.Run(tt.name, func(t *testing.T) {
  2265  			require := require.New(t)
  2266  			a := &Allocation{
  2267  				DataShards:   2,
  2268  				ParityShards: 2,
  2269  			}
  2270  			setupMockAllocation(t, a)
  2271  			for i := 0; i < numBlobbers; i++ {
  2272  				a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  2273  					ID:      tt.name + mockBlobberId + strconv.Itoa(i),
  2274  					Baseurl: "TestAllocation_StartRepair" + tt.name + mockBlobberUrl + strconv.Itoa(i),
  2275  				})
  2276  			}
  2277  			if tt.setup != nil {
  2278  				if teardown := tt.setup(t, tt.name, a); teardown != nil {
  2279  					defer teardown(t)
  2280  				}
  2281  			}
  2282  			err := a.StartRepair(tt.parameters.localPath, tt.parameters.pathToRepair, tt.parameters.statusCallback)
  2283  			require.EqualValues(tt.wantErr, err != nil)
  2284  			if err != nil {
  2285  				require.EqualValues(tt.errMsg, errors.Top(err))
  2286  				return
  2287  			}
  2288  			require.NoErrorf(err, "unexpected error: %v", err)
  2289  		})
  2290  	}
  2291  }
  2292  
  2293  func TestAllocation_CancelRepair(t *testing.T) {
  2294  	tests := []struct {
  2295  		name    string
  2296  		setup   func(*testing.T, *Allocation) (teardown func(*testing.T))
  2297  		wantErr bool
  2298  		errMsg  string
  2299  	}{
  2300  		{
  2301  			name:    "Test_Failed",
  2302  			wantErr: true,
  2303  			errMsg:  "invalid_cancel_repair_request: No repair in progress for the allocation",
  2304  		},
  2305  		{
  2306  			name: "Test_Success",
  2307  			setup: func(t *testing.T, a *Allocation) (teardown func(t *testing.T)) {
  2308  				a.repairRequestInProgress = &RepairRequest{}
  2309  				return nil
  2310  			},
  2311  		},
  2312  	}
  2313  	for _, tt := range tests {
  2314  		t.Run(tt.name, func(t *testing.T) {
  2315  			require := require.New(t)
  2316  			a := &Allocation{}
  2317  			setupMockAllocation(t, a)
  2318  			if tt.setup != nil {
  2319  				if teardown := tt.setup(t, a); teardown != nil {
  2320  					defer teardown(t)
  2321  				}
  2322  			}
  2323  			err := a.CancelRepair()
  2324  			require.EqualValues(tt.wantErr, err != nil)
  2325  			if err != nil {
  2326  				require.EqualValues(tt.errMsg, errors.Top(err))
  2327  				return
  2328  			}
  2329  			require.NoErrorf(err, "unexpected error: %v", err)
  2330  		})
  2331  	}
  2332  }
  2333  
  2334  func setupMockAllocation(t *testing.T, a *Allocation) {
  2335  	a.downloadChan = make(chan *DownloadRequest, 10)
  2336  	a.repairChan = make(chan *RepairRequest, 1)
  2337  	a.ctx, a.ctxCancelF = context.WithCancel(context.Background())
  2338  	a.downloadProgressMap = make(map[string]*DownloadRequest)
  2339  	a.mutex = &sync.Mutex{}
  2340  	a.FileOptions = uint16(63) // 0011 1111 All allowed
  2341  	InitCommitWorker(a.Blobbers)
  2342  	a.initialized = true
  2343  	if a.DataShards != 0 {
  2344  		a.fullconsensus, a.consensusThreshold = a.getConsensuses()
  2345  	}
  2346  	sdkInitialized = true
  2347  
  2348  	go func() {
  2349  		for {
  2350  			select {
  2351  			case <-a.ctx.Done():
  2352  				t.Log("Upload cancelled by the parent")
  2353  				return
  2354  			case downloadReq := <-a.downloadChan:
  2355  				remotePathCB := downloadReq.remotefilepath
  2356  				if remotePathCB == "" {
  2357  					remotePathCB = downloadReq.remotefilepathhash
  2358  				}
  2359  				if downloadReq.completedCallback != nil {
  2360  					downloadReq.completedCallback(downloadReq.remotefilepath, downloadReq.remotefilepathhash)
  2361  				}
  2362  				if downloadReq.statusCallback != nil {
  2363  					downloadReq.statusCallback.Completed(a.ID, remotePathCB, "1.txt", "application/octet-stream", 3, OpDownload)
  2364  				}
  2365  				t.Logf("received a download request for %v\n", downloadReq.remotefilepath)
  2366  			case repairReq := <-a.repairChan:
  2367  				if repairReq.completedCallback != nil {
  2368  					repairReq.completedCallback()
  2369  				}
  2370  				if repairReq.wg != nil {
  2371  					repairReq.wg.Done()
  2372  				}
  2373  				t.Logf("received a repair request for %v\n", repairReq.listDir.Path)
  2374  			}
  2375  		}
  2376  	}()
  2377  }
  2378  
  2379  func setupMockGetFileInfoResponse(t *testing.T, mockClient *mocks.HttpClient) {
  2380  	httpResponse := http.Response{
  2381  		StatusCode: http.StatusOK,
  2382  		Body: func() io.ReadCloser {
  2383  			jsonFR, err := json.Marshal(fileref.FileRef{
  2384  				Ref: fileref.Ref{
  2385  					Name: mockFileRefName,
  2386  				},
  2387  				ValidationRoot: "mock validation root",
  2388  			})
  2389  			require.NoError(t, err)
  2390  			return ioutil.NopCloser(bytes.NewReader([]byte(jsonFR)))
  2391  		}(),
  2392  	}
  2393  	for i := 0; i < numBlobbers; i++ {
  2394  		mockClient.On("Do", mock.Anything).Return(&httpResponse, nil)
  2395  	}
  2396  }
  2397  
  2398  func getMockAuthTicket(t *testing.T) string {
  2399  	var mockClient = mocks.HttpClient{}
  2400  	zboxutil.Client = &mockClient
  2401  
  2402  	client := zclient.GetClient()
  2403  	client.Wallet = &zcncrypto.Wallet{
  2404  		ClientID:  mockClientId,
  2405  		ClientKey: mockClientKey,
  2406  	}
  2407  	a := &Allocation{
  2408  		ID:           mockAllocationId,
  2409  		Tx:           mockAllocationTxId,
  2410  		DataShards:   1,
  2411  		ParityShards: 1,
  2412  		FileOptions:  63,
  2413  	}
  2414  
  2415  	a.InitAllocation()
  2416  	sdkInitialized = true
  2417  	for i := 0; i < numBlobbers; i++ {
  2418  		a.Blobbers = append(a.Blobbers, &blockchain.StorageNode{
  2419  			ID:      strconv.Itoa(i),
  2420  			Baseurl: "TestAllocation_getMockAuthTicket" + mockBlobberUrl + strconv.Itoa(i),
  2421  		})
  2422  	}
  2423  
  2424  	jsonFR, err := json.Marshal(fileref.FileRef{
  2425  		Ref: fileref.Ref{
  2426  			Name: mockFileRefName,
  2427  		},
  2428  		ValidationRoot: "mock validation root",
  2429  		EncryptedKey:   "encrypted key",
  2430  	})
  2431  	require.NoError(t, err)
  2432  
  2433  	httpResponse := &http.Response{
  2434  		StatusCode: http.StatusOK,
  2435  		Body: func() io.ReadCloser {
  2436  			return ioutil.NopCloser(bytes.NewReader(jsonFR))
  2437  		}(),
  2438  	}
  2439  
  2440  	setupMockGetFileMetaResponse(t, &mockClient, "TestAllocation_getMockAuthTicket", "", a, http.MethodPost, http.StatusOK, jsonFR)
  2441  
  2442  	for i := 0; i < numBlobbers; i++ {
  2443  		mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
  2444  			return strings.HasPrefix(req.URL.Path, "TestAllocation_ListDirFromAuthTicket")
  2445  		})).Return(httpResponse, nil)
  2446  
  2447  		mockClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
  2448  			return strings.HasPrefix(req.URL.Path, "TestAllocation_getMockAuthTicket")
  2449  		})).Return(httpResponse, nil)
  2450  	}
  2451  
  2452  	authTicket, err := a.GetAuthTicket("/1.txt", "1.txt", fileref.FILE, mockClientId, "", 0, nil)
  2453  	require.NoErrorf(t, err, "unexpected get auth ticket error: %v", err)
  2454  	require.NotEmptyf(t, authTicket, "unexpected empty auth ticket")
  2455  	return authTicket
  2456  }