main.TestRead   D
last analyzed

Complexity

Conditions 13

Size

Total Lines 78
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 50
nop 1
dl 0
loc 78
rs 4.2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like main.TestRead often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package main
2
3
import (
4
	"encoding/json"
5
	"os"
6
	"os/user"
7
	"path/filepath"
8
	"testing"
9
)
10
11
func TestStateSave(t *testing.T) {
12
	// Setup test environment
13
	originalDataFolder := dataFolder
14
	dataFolder = ".hget_test/"
15
	defer func() {
16
		dataFolder = originalDataFolder
17
		usr, _ := user.Current()
18
		testFolder := filepath.Join(usr.HomeDir, dataFolder)
19
		os.RemoveAll(testFolder)
20
	}()
21
22
	// Create test state
23
	testURL := "http://example.com/test.zip"
24
	s := &State{
25
		URL: testURL,
26
		Parts: []Part{
27
			{
28
				Index:     0,
29
				URL:       testURL,
30
				Path:      "temp_part0",
31
				RangeFrom: 0,
32
				RangeTo:   100,
33
			},
34
			{
35
				Index:     1,
36
				URL:       testURL,
37
				Path:      "temp_part1",
38
				RangeFrom: 101,
39
				RangeTo:   200,
40
			},
41
		},
42
	}
43
44
	// Create temporary files for parts
45
	for _, part := range s.Parts {
46
		err := os.WriteFile(part.Path, []byte("test content"), 0644)
47
		if err != nil {
48
			t.Fatalf("Failed to create test file: %v", err)
49
		}
50
		defer os.Remove(part.Path) // Cleanup in case the test fails
51
	}
52
53
	// Test Save method
54
	err := s.Save()
55
	if err != nil {
56
		t.Fatalf("Save() failed: %v", err)
57
	}
58
59
	// Verify state file was created
60
	folder := FolderOf(testURL)
61
	stateFilePath := filepath.Join(folder, stateFileName)
62
63
	if _, err := os.Stat(stateFilePath); os.IsNotExist(err) {
64
		t.Fatalf("State file was not created at %s", stateFilePath)
65
	}
66
67
	// Verify content of the state file
68
	stateBytes, err := os.ReadFile(stateFilePath)
69
	if err != nil {
70
		t.Fatalf("Could not read state file: %v", err)
71
	}
72
73
	var savedState State
74
	err = json.Unmarshal(stateBytes, &savedState)
75
	if err != nil {
76
		t.Fatalf("Could not unmarshal state file: %v", err)
77
	}
78
79
	if savedState.URL != testURL {
80
		t.Errorf("Expected URL %s, got %s", testURL, savedState.URL)
81
	}
82
83
	if len(savedState.Parts) != len(s.Parts) {
84
		t.Errorf("Expected %d parts, got %d", len(s.Parts), len(savedState.Parts))
85
	}
86
87
	// Verify part files were moved
88
	for _, part := range s.Parts {
89
		movedPath := filepath.Join(folder, filepath.Base(part.Path))
90
		if _, err := os.Stat(movedPath); os.IsNotExist(err) {
91
			t.Errorf("Part file not moved to %s", movedPath)
92
		} else {
93
			// Clean up moved files
94
			os.Remove(movedPath)
95
		}
96
	}
97
}
98
99
func TestRead(t *testing.T) {
100
	// Setup test environment
101
	originalDataFolder := dataFolder
102
	dataFolder = ".hget_test/"
103
	defer func() {
104
		dataFolder = originalDataFolder
105
		usr, _ := user.Current()
106
		testFolder := filepath.Join(usr.HomeDir, dataFolder)
107
		os.RemoveAll(testFolder)
108
	}()
109
110
	// Create test data
111
	testURL := "http://example.com/test.zip"
112
	testState := &State{
113
		URL: testURL,
114
		Parts: []Part{
115
			{
116
				Index:     0,
117
				URL:       testURL,
118
				Path:      "part0",
119
				RangeFrom: 0,
120
				RangeTo:   100,
121
			},
122
			{
123
				Index:     1,
124
				URL:       testURL,
125
				Path:      "part1",
126
				RangeFrom: 101,
127
				RangeTo:   200,
128
			},
129
		},
130
	}
131
132
	// Set up directory structure
133
	usr, _ := user.Current()
134
	homeDir := usr.HomeDir
135
	taskName := TaskFromURL(testURL)
136
	folderPath := filepath.Join(homeDir, dataFolder, taskName)
137
	stateFilePath := filepath.Join(folderPath, stateFileName)
138
139
	// Create directory
140
	err := os.MkdirAll(folderPath, 0755)
141
	if err != nil {
142
		t.Fatalf("Failed to create test directory: %v", err)
143
	}
144
145
	// Write test state file
146
	stateData, err := json.Marshal(testState)
147
	if err != nil {
148
		t.Fatalf("Failed to marshal test state: %v", err)
149
	}
150
151
	err = os.WriteFile(stateFilePath, stateData, 0644)
152
	if err != nil {
153
		t.Fatalf("Failed to write test state file: %v", err)
154
	}
155
156
	// Test Read function
157
	state, err := Read(testURL)
158
	if err != nil {
159
		t.Fatalf("Read() failed: %v", err)
160
	}
161
162
	// Verify the read state matches the test state
163
	if state.URL != testState.URL {
164
		t.Errorf("Expected URL %s, got %s", testState.URL, state.URL)
165
	}
166
167
	if len(state.Parts) != len(testState.Parts) {
168
		t.Errorf("Expected %d parts, got %d", len(testState.Parts), len(state.Parts))
169
	}
170
171
	for i, part := range state.Parts {
172
		if part.Index != testState.Parts[i].Index ||
173
			part.URL != testState.Parts[i].URL ||
174
			part.RangeFrom != testState.Parts[i].RangeFrom ||
175
			part.RangeTo != testState.Parts[i].RangeTo {
176
			t.Errorf("Part %d does not match expected values", i)
177
		}
178
	}
179
}
180
181
func TestReadNonExistent(t *testing.T) {
182
	// Test reading a non-existent state file
183
	_, err := Read("http://nonexistent.example.com/file.zip")
184
	if err == nil {
185
		t.Errorf("Expected error when reading non-existent state, got nil")
186
	}
187
}
188