Refactor core tests and improve mock implementations
Signed-off-by: Snider <snider@lt.hn>
This commit is contained in:
parent
d25bd5c5ca
commit
5d4e081143
12 changed files with 443 additions and 2193 deletions
1
.github/workflows/docs.yml
vendored
1
.github/workflows/docs.yml
vendored
|
|
@ -18,5 +18,4 @@ jobs:
|
|||
with:
|
||||
python-version: 3.x
|
||||
- run: pip install mkdocs-material
|
||||
- run: go run ./cmd/core dev docgen
|
||||
- run: mkdocs gh-deploy --force
|
||||
|
|
|
|||
10
Taskfile.yml
10
Taskfile.yml
|
|
@ -42,13 +42,3 @@ tasks:
|
|||
cmds:
|
||||
- task: cov
|
||||
- go tool cover -html=coverage.txt
|
||||
|
||||
sync:
|
||||
desc: "Updates the public API Go files to match the exported interface of the modules."
|
||||
cmds:
|
||||
- task: cli:sync
|
||||
|
||||
test-gen:
|
||||
desc: "Generates tests for the public API."
|
||||
cmds:
|
||||
- task: cli:test-gen
|
||||
|
|
|
|||
|
|
@ -19,155 +19,36 @@ The key features of this package are:
|
|||
- Consistent error handling: Encourages a uniform approach to error
|
||||
handling across the entire codebase.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## Types
|
||||
|
||||
### `type Error`
|
||||
|
||||
`Error` represents a standardized error with operational context.
|
||||
|
||||
```go
|
||||
type Error 0 *ast.StructType {
|
||||
1 . Struct: -
|
||||
2 . Fields: *ast.FieldList {
|
||||
3 . . Opening: -
|
||||
4 . . List: []*ast.Field (len = 3) {
|
||||
5 . . . 0: *ast.Field {
|
||||
6 . . . . Doc: *ast.CommentGroup {
|
||||
7 . . . . . List: []*ast.Comment (len = 1) {
|
||||
8 . . . . . . 0: *ast.Comment {
|
||||
9 . . . . . . . Slash: -
|
||||
10 . . . . . . . Text: "// Op is the operation being performed, e.g., \"config.Load\"."
|
||||
11 . . . . . . }
|
||||
12 . . . . . }
|
||||
13 . . . . }
|
||||
14 . . . . Names: []*ast.Ident (len = 1) {
|
||||
15 . . . . . 0: *ast.Ident {
|
||||
16 . . . . . . NamePos: -
|
||||
17 . . . . . . Name: "Op"
|
||||
18 . . . . . . Obj: *ast.Object {
|
||||
19 . . . . . . . Kind: var
|
||||
20 . . . . . . . Name: "Op"
|
||||
21 . . . . . . . Decl: *(obj @ 5)
|
||||
22 . . . . . . . Data: nil
|
||||
23 . . . . . . . Type: nil
|
||||
24 . . . . . . }
|
||||
25 . . . . . }
|
||||
26 . . . . }
|
||||
27 . . . . Type: *ast.Ident {
|
||||
28 . . . . . NamePos: -
|
||||
29 . . . . . Name: "string"
|
||||
30 . . . . . Obj: nil
|
||||
31 . . . . }
|
||||
32 . . . . Tag: nil
|
||||
33 . . . . Comment: nil
|
||||
34 . . . }
|
||||
35 . . . 1: *ast.Field {
|
||||
36 . . . . Doc: *ast.CommentGroup {
|
||||
37 . . . . . List: []*ast.Comment (len = 1) {
|
||||
38 . . . . . . 0: *ast.Comment {
|
||||
39 . . . . . . . Slash: -
|
||||
40 . . . . . . . Text: "// Msg is a human-readable message explaining the error."
|
||||
41 . . . . . . }
|
||||
42 . . . . . }
|
||||
43 . . . . }
|
||||
44 . . . . Names: []*ast.Ident (len = 1) {
|
||||
45 . . . . . 0: *ast.Ident {
|
||||
46 . . . . . . NamePos: -
|
||||
47 . . . . . . Name: "Msg"
|
||||
48 . . . . . . Obj: *ast.Object {
|
||||
49 . . . . . . . Kind: var
|
||||
50 . . . . . . . Name: "Msg"
|
||||
51 . . . . . . . Decl: *(obj @ 35)
|
||||
52 . . . . . . . Data: nil
|
||||
53 . . . . . . . Type: nil
|
||||
54 . . . . . . }
|
||||
55 . . . . . }
|
||||
56 . . . . }
|
||||
57 . . . . Type: *ast.Ident {
|
||||
58 . . . . . NamePos: -
|
||||
59 . . . . . Name: "string"
|
||||
60 . . . . . Obj: nil
|
||||
61 . . . . }
|
||||
62 . . . . Tag: nil
|
||||
63 . . . . Comment: nil
|
||||
64 . . . }
|
||||
65 . . . 2: *ast.Field {
|
||||
66 . . . . Doc: *ast.CommentGroup {
|
||||
67 . . . . . List: []*ast.Comment (len = 1) {
|
||||
68 . . . . . . 0: *ast.Comment {
|
||||
69 . . . . . . . Slash: -
|
||||
70 . . . . . . . Text: "// Err is the underlying error that was wrapped."
|
||||
71 . . . . . . }
|
||||
72 . . . . . }
|
||||
73 . . . . }
|
||||
74 . . . . Names: []*ast.Ident (len = 1) {
|
||||
75 . . . . . 0: *ast.Ident {
|
||||
76 . . . . . . NamePos: -
|
||||
77 . . . . . . Name: "Err"
|
||||
78 . . . . . . Obj: *ast.Object {
|
||||
79 . . . . . . . Kind: var
|
||||
80 . . . . . . . Name: "Err"
|
||||
81 . . . . . . . Decl: *(obj @ 65)
|
||||
82 . . . . . . . Data: nil
|
||||
83 . . . . . . . Type: nil
|
||||
84 . . . . . . }
|
||||
85 . . . . . }
|
||||
86 . . . . }
|
||||
87 . . . . Type: *ast.Ident {
|
||||
88 . . . . . NamePos: -
|
||||
89 . . . . . Name: "error"
|
||||
90 . . . . . Obj: nil
|
||||
91 . . . . }
|
||||
92 . . . . Tag: nil
|
||||
93 . . . . Comment: nil
|
||||
94 . . . }
|
||||
95 . . }
|
||||
96 . . Closing: -
|
||||
97 . }
|
||||
98 . Incomplete: false
|
||||
99 }
|
||||
|
||||
type Error struct {
|
||||
// Op is the operation being performed, e.g., "config.Load".
|
||||
Op string
|
||||
// Msg is a human-readable message explaining the error.
|
||||
Msg string
|
||||
// Err is the underlying error that was wrapped.
|
||||
Err error
|
||||
}
|
||||
```
|
||||
Error represents a standardized error with operational context.
|
||||
|
||||
|
||||
|
||||
#### Methods
|
||||
|
||||
- `Error() 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: Error returns the string representation of the error.
|
||||
|
||||
- `Unwrap() 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: Unwrap provides compatibility for Go's errors.Is and errors.As functions.
|
||||
|
||||
|
||||
|
||||
|
||||
- `Error() string`: Error returns the string representation of the error.
|
||||
- `Unwrap() error`: Unwrap provides compatibility for Go's errors.Is and errors.As functions.
|
||||
|
||||
## Functions
|
||||
|
||||
- `E(op, msg 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, err 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: E is a helper function to create a new Error. This is the primary way to create errors that will be consumed by the system. For example: return e.E("config.Load", "failed to load config file", err) The 'op' parameter should be in the format of 'package.function' or 'service.method'. The 'msg' parameter should be a human-readable message that can be displayed to the user. The 'err' parameter is the underlying error that is being wrapped.
|
||||
- `E(op, msg string, err error) error`: E is a helper function to create a new Error.
|
||||
|
||||
This is the primary way to create errors that will be consumed by the system. For example:
|
||||
|
||||
```go
|
||||
return e.E("config.Load", "failed to load config file", err)
|
||||
```
|
||||
|
||||
The `op` parameter should be in the format of `package.function` or `service.method`. The `msg` parameter should be a human-readable message that can be displayed to the user. The `err` parameter is the underlying error that is being wrapped.
|
||||
|
|
|
|||
|
|
@ -3,795 +3,62 @@ title: io
|
|||
---
|
||||
# Service: `io`
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
The `io` service provides a standardized interface for interacting with different storage backends, such as the local disk, S3, or SFTP.
|
||||
|
||||
## Types
|
||||
|
||||
### `type Medium`
|
||||
|
||||
`Medium` defines the standard interface for a storage backend.
|
||||
|
||||
```go
|
||||
type Medium 0 *ast.InterfaceType {
|
||||
1 . Interface: -
|
||||
2 . Methods: *ast.FieldList {
|
||||
3 . . Opening: -
|
||||
4 . . List: []*ast.Field (len = 6) {
|
||||
5 . . . 0: *ast.Field {
|
||||
6 . . . . Doc: *ast.CommentGroup {
|
||||
7 . . . . . List: []*ast.Comment (len = 1) {
|
||||
8 . . . . . . 0: *ast.Comment {
|
||||
9 . . . . . . . Slash: -
|
||||
10 . . . . . . . Text: "// Read retrieves the content of a file as a string."
|
||||
11 . . . . . . }
|
||||
12 . . . . . }
|
||||
13 . . . . }
|
||||
14 . . . . Names: []*ast.Ident (len = 1) {
|
||||
15 . . . . . 0: *ast.Ident {
|
||||
16 . . . . . . NamePos: -
|
||||
17 . . . . . . Name: "Read"
|
||||
18 . . . . . . Obj: *ast.Object {
|
||||
19 . . . . . . . Kind: func
|
||||
20 . . . . . . . Name: "Read"
|
||||
21 . . . . . . . Decl: *(obj @ 5)
|
||||
22 . . . . . . . Data: nil
|
||||
23 . . . . . . . Type: nil
|
||||
24 . . . . . . }
|
||||
25 . . . . . }
|
||||
26 . . . . }
|
||||
27 . . . . Type: *ast.FuncType {
|
||||
28 . . . . . Func: -
|
||||
29 . . . . . TypeParams: nil
|
||||
30 . . . . . Params: *ast.FieldList {
|
||||
31 . . . . . . Opening: -
|
||||
32 . . . . . . List: []*ast.Field (len = 1) {
|
||||
33 . . . . . . . 0: *ast.Field {
|
||||
34 . . . . . . . . Doc: nil
|
||||
35 . . . . . . . . Names: []*ast.Ident (len = 1) {
|
||||
36 . . . . . . . . . 0: *ast.Ident {
|
||||
37 . . . . . . . . . . NamePos: -
|
||||
38 . . . . . . . . . . Name: "path"
|
||||
39 . . . . . . . . . . Obj: *ast.Object {
|
||||
40 . . . . . . . . . . . Kind: var
|
||||
41 . . . . . . . . . . . Name: "path"
|
||||
42 . . . . . . . . . . . Decl: *(obj @ 33)
|
||||
43 . . . . . . . . . . . Data: nil
|
||||
44 . . . . . . . . . . . Type: nil
|
||||
45 . . . . . . . . . . }
|
||||
46 . . . . . . . . . }
|
||||
47 . . . . . . . . }
|
||||
48 . . . . . . . . Type: *ast.Ident {
|
||||
49 . . . . . . . . . NamePos: -
|
||||
50 . . . . . . . . . Name: "string"
|
||||
51 . . . . . . . . . Obj: nil
|
||||
52 . . . . . . . . }
|
||||
53 . . . . . . . . Tag: nil
|
||||
54 . . . . . . . . Comment: nil
|
||||
55 . . . . . . . }
|
||||
56 . . . . . . }
|
||||
57 . . . . . . Closing: -
|
||||
58 . . . . . }
|
||||
59 . . . . . Results: *ast.FieldList {
|
||||
60 . . . . . . Opening: -
|
||||
61 . . . . . . List: []*ast.Field (len = 2) {
|
||||
62 . . . . . . . 0: *ast.Field {
|
||||
63 . . . . . . . . Doc: nil
|
||||
64 . . . . . . . . Names: nil
|
||||
65 . . . . . . . . Type: *ast.Ident {
|
||||
66 . . . . . . . . . NamePos: -
|
||||
67 . . . . . . . . . Name: "string"
|
||||
68 . . . . . . . . . Obj: nil
|
||||
69 . . . . . . . . }
|
||||
70 . . . . . . . . Tag: nil
|
||||
71 . . . . . . . . Comment: nil
|
||||
72 . . . . . . . }
|
||||
73 . . . . . . . 1: *ast.Field {
|
||||
74 . . . . . . . . Doc: nil
|
||||
75 . . . . . . . . Names: nil
|
||||
76 . . . . . . . . Type: *ast.Ident {
|
||||
77 . . . . . . . . . NamePos: -
|
||||
78 . . . . . . . . . Name: "error"
|
||||
79 . . . . . . . . . Obj: nil
|
||||
80 . . . . . . . . }
|
||||
81 . . . . . . . . Tag: nil
|
||||
82 . . . . . . . . Comment: nil
|
||||
83 . . . . . . . }
|
||||
84 . . . . . . }
|
||||
85 . . . . . . Closing: -
|
||||
86 . . . . . }
|
||||
87 . . . . }
|
||||
88 . . . . Tag: nil
|
||||
89 . . . . Comment: nil
|
||||
90 . . . }
|
||||
91 . . . 1: *ast.Field {
|
||||
92 . . . . Doc: *ast.CommentGroup {
|
||||
93 . . . . . List: []*ast.Comment (len = 1) {
|
||||
94 . . . . . . 0: *ast.Comment {
|
||||
95 . . . . . . . Slash: -
|
||||
96 . . . . . . . Text: "// Write saves the given content to a file, overwriting it if it exists."
|
||||
97 . . . . . . }
|
||||
98 . . . . . }
|
||||
99 . . . . }
|
||||
100 . . . . Names: []*ast.Ident (len = 1) {
|
||||
101 . . . . . 0: *ast.Ident {
|
||||
102 . . . . . . NamePos: -
|
||||
103 . . . . . . Name: "Write"
|
||||
104 . . . . . . Obj: *ast.Object {
|
||||
105 . . . . . . . Kind: func
|
||||
106 . . . . . . . Name: "Write"
|
||||
107 . . . . . . . Decl: *(obj @ 91)
|
||||
108 . . . . . . . Data: nil
|
||||
109 . . . . . . . Type: nil
|
||||
110 . . . . . . }
|
||||
111 . . . . . }
|
||||
112 . . . . }
|
||||
113 . . . . Type: *ast.FuncType {
|
||||
114 . . . . . Func: -
|
||||
115 . . . . . TypeParams: nil
|
||||
116 . . . . . Params: *ast.FieldList {
|
||||
117 . . . . . . Opening: -
|
||||
118 . . . . . . List: []*ast.Field (len = 1) {
|
||||
119 . . . . . . . 0: *ast.Field {
|
||||
120 . . . . . . . . Doc: nil
|
||||
121 . . . . . . . . Names: []*ast.Ident (len = 2) {
|
||||
122 . . . . . . . . . 0: *ast.Ident {
|
||||
123 . . . . . . . . . . NamePos: -
|
||||
124 . . . . . . . . . . Name: "path"
|
||||
125 . . . . . . . . . . Obj: *ast.Object {
|
||||
126 . . . . . . . . . . . Kind: var
|
||||
127 . . . . . . . . . . . Name: "path"
|
||||
128 . . . . . . . . . . . Decl: *(obj @ 119)
|
||||
129 . . . . . . . . . . . Data: nil
|
||||
130 . . . . . . . . . . . Type: nil
|
||||
131 . . . . . . . . . . }
|
||||
132 . . . . . . . . . }
|
||||
133 . . . . . . . . . 1: *ast.Ident {
|
||||
134 . . . . . . . . . . NamePos: -
|
||||
135 . . . . . . . . . . Name: "content"
|
||||
136 . . . . . . . . . . Obj: *ast.Object {
|
||||
137 . . . . . . . . . . . Kind: var
|
||||
138 . . . . . . . . . . . Name: "content"
|
||||
139 . . . . . . . . . . . Decl: *(obj @ 119)
|
||||
140 . . . . . . . . . . . Data: nil
|
||||
141 . . . . . . . . . . . Type: nil
|
||||
142 . . . . . . . . . . }
|
||||
143 . . . . . . . . . }
|
||||
144 . . . . . . . . }
|
||||
145 . . . . . . . . Type: *ast.Ident {
|
||||
146 . . . . . . . . . NamePos: -
|
||||
147 . . . . . . . . . Name: "string"
|
||||
148 . . . . . . . . . Obj: nil
|
||||
149 . . . . . . . . }
|
||||
150 . . . . . . . . Tag: nil
|
||||
151 . . . . . . . . Comment: nil
|
||||
152 . . . . . . . }
|
||||
153 . . . . . . }
|
||||
154 . . . . . . Closing: -
|
||||
155 . . . . . }
|
||||
156 . . . . . Results: *ast.FieldList {
|
||||
157 . . . . . . Opening: -
|
||||
158 . . . . . . List: []*ast.Field (len = 1) {
|
||||
159 . . . . . . . 0: *ast.Field {
|
||||
160 . . . . . . . . Doc: nil
|
||||
161 . . . . . . . . Names: nil
|
||||
162 . . . . . . . . Type: *ast.Ident {
|
||||
163 . . . . . . . . . NamePos: -
|
||||
164 . . . . . . . . . Name: "error"
|
||||
165 . . . . . . . . . Obj: nil
|
||||
166 . . . . . . . . }
|
||||
167 . . . . . . . . Tag: nil
|
||||
168 . . . . . . . . Comment: nil
|
||||
169 . . . . . . . }
|
||||
170 . . . . . . }
|
||||
171 . . . . . . Closing: -
|
||||
172 . . . . . }
|
||||
173 . . . . }
|
||||
174 . . . . Tag: nil
|
||||
175 . . . . Comment: nil
|
||||
176 . . . }
|
||||
177 . . . 2: *ast.Field {
|
||||
178 . . . . Doc: *ast.CommentGroup {
|
||||
179 . . . . . List: []*ast.Comment (len = 1) {
|
||||
180 . . . . . . 0: *ast.Comment {
|
||||
181 . . . . . . . Slash: -
|
||||
182 . . . . . . . Text: "// EnsureDir makes sure a directory exists, creating it if necessary."
|
||||
183 . . . . . . }
|
||||
184 . . . . . }
|
||||
185 . . . . }
|
||||
186 . . . . Names: []*ast.Ident (len = 1) {
|
||||
187 . . . . . 0: *ast.Ident {
|
||||
188 . . . . . . NamePos: -
|
||||
189 . . . . . . Name: "EnsureDir"
|
||||
190 . . . . . . Obj: *ast.Object {
|
||||
191 . . . . . . . Kind: func
|
||||
192 . . . . . . . Name: "EnsureDir"
|
||||
193 . . . . . . . Decl: *(obj @ 177)
|
||||
194 . . . . . . . Data: nil
|
||||
195 . . . . . . . Type: nil
|
||||
196 . . . . . . }
|
||||
197 . . . . . }
|
||||
198 . . . . }
|
||||
199 . . . . Type: *ast.FuncType {
|
||||
200 . . . . . Func: -
|
||||
201 . . . . . TypeParams: nil
|
||||
202 . . . . . Params: *ast.FieldList {
|
||||
203 . . . . . . Opening: -
|
||||
204 . . . . . . List: []*ast.Field (len = 1) {
|
||||
205 . . . . . . . 0: *ast.Field {
|
||||
206 . . . . . . . . Doc: nil
|
||||
207 . . . . . . . . Names: []*ast.Ident (len = 1) {
|
||||
208 . . . . . . . . . 0: *ast.Ident {
|
||||
209 . . . . . . . . . . NamePos: -
|
||||
210 . . . . . . . . . . Name: "path"
|
||||
211 . . . . . . . . . . Obj: *ast.Object {
|
||||
212 . . . . . . . . . . . Kind: var
|
||||
213 . . . . . . . . . . . Name: "path"
|
||||
214 . . . . . . . . . . . Decl: *(obj @ 205)
|
||||
215 . . . . . . . . . . . Data: nil
|
||||
216 . . . . . . . . . . . Type: nil
|
||||
217 . . . . . . . . . . }
|
||||
218 . . . . . . . . . }
|
||||
219 . . . . . . . . }
|
||||
220 . . . . . . . . Type: *ast.Ident {
|
||||
221 . . . . . . . . . NamePos: -
|
||||
222 . . . . . . . . . Name: "string"
|
||||
223 . . . . . . . . . Obj: nil
|
||||
224 . . . . . . . . }
|
||||
225 . . . . . . . . Tag: nil
|
||||
226 . . . . . . . . Comment: nil
|
||||
227 . . . . . . . }
|
||||
228 . . . . . . }
|
||||
229 . . . . . . Closing: -
|
||||
230 . . . . . }
|
||||
231 . . . . . Results: *ast.FieldList {
|
||||
232 . . . . . . Opening: -
|
||||
233 . . . . . . List: []*ast.Field (len = 1) {
|
||||
234 . . . . . . . 0: *ast.Field {
|
||||
235 . . . . . . . . Doc: nil
|
||||
236 . . . . . . . . Names: nil
|
||||
237 . . . . . . . . Type: *ast.Ident {
|
||||
238 . . . . . . . . . NamePos: -
|
||||
239 . . . . . . . . . Name: "error"
|
||||
240 . . . . . . . . . Obj: nil
|
||||
241 . . . . . . . . }
|
||||
242 . . . . . . . . Tag: nil
|
||||
243 . . . . . . . . Comment: nil
|
||||
244 . . . . . . . }
|
||||
245 . . . . . . }
|
||||
246 . . . . . . Closing: -
|
||||
247 . . . . . }
|
||||
248 . . . . }
|
||||
249 . . . . Tag: nil
|
||||
250 . . . . Comment: nil
|
||||
251 . . . }
|
||||
252 . . . 3: *ast.Field {
|
||||
253 . . . . Doc: *ast.CommentGroup {
|
||||
254 . . . . . List: []*ast.Comment (len = 1) {
|
||||
255 . . . . . . 0: *ast.Comment {
|
||||
256 . . . . . . . Slash: -
|
||||
257 . . . . . . . Text: "// IsFile checks if a path exists and is a regular file."
|
||||
258 . . . . . . }
|
||||
259 . . . . . }
|
||||
260 . . . . }
|
||||
261 . . . . Names: []*ast.Ident (len = 1) {
|
||||
262 . . . . . 0: *ast.Ident {
|
||||
263 . . . . . . NamePos: -
|
||||
264 . . . . . . Name: "IsFile"
|
||||
265 . . . . . . Obj: *ast.Object {
|
||||
266 . . . . . . . Kind: func
|
||||
267 . . . . . . . Name: "IsFile"
|
||||
268 . . . . . . . Decl: *(obj @ 252)
|
||||
269 . . . . . . . Data: nil
|
||||
270 . . . . . . . Type: nil
|
||||
271 . . . . . . }
|
||||
272 . . . . . }
|
||||
273 . . . . }
|
||||
274 . . . . Type: *ast.FuncType {
|
||||
275 . . . . . Func: -
|
||||
276 . . . . . TypeParams: nil
|
||||
277 . . . . . Params: *ast.FieldList {
|
||||
278 . . . . . . Opening: -
|
||||
279 . . . . . . List: []*ast.Field (len = 1) {
|
||||
280 . . . . . . . 0: *ast.Field {
|
||||
281 . . . . . . . . Doc: nil
|
||||
282 . . . . . . . . Names: []*ast.Ident (len = 1) {
|
||||
283 . . . . . . . . . 0: *ast.Ident {
|
||||
284 . . . . . . . . . . NamePos: -
|
||||
285 . . . . . . . . . . Name: "path"
|
||||
286 . . . . . . . . . . Obj: *ast.Object {
|
||||
287 . . . . . . . . . . . Kind: var
|
||||
288 . . . . . . . . . . . Name: "path"
|
||||
289 . . . . . . . . . . . Decl: *(obj @ 280)
|
||||
290 . . . . . . . . . . . Data: nil
|
||||
291 . . . . . . . . . . . Type: nil
|
||||
292 . . . . . . . . . . }
|
||||
293 . . . . . . . . . }
|
||||
294 . . . . . . . . }
|
||||
295 . . . . . . . . Type: *ast.Ident {
|
||||
296 . . . . . . . . . NamePos: -
|
||||
297 . . . . . . . . . Name: "string"
|
||||
298 . . . . . . . . . Obj: nil
|
||||
299 . . . . . . . . }
|
||||
300 . . . . . . . . Tag: nil
|
||||
301 . . . . . . . . Comment: nil
|
||||
302 . . . . . . . }
|
||||
303 . . . . . . }
|
||||
304 . . . . . . Closing: -
|
||||
305 . . . . . }
|
||||
306 . . . . . Results: *ast.FieldList {
|
||||
307 . . . . . . Opening: -
|
||||
308 . . . . . . List: []*ast.Field (len = 1) {
|
||||
309 . . . . . . . 0: *ast.Field {
|
||||
310 . . . . . . . . Doc: nil
|
||||
311 . . . . . . . . Names: nil
|
||||
312 . . . . . . . . Type: *ast.Ident {
|
||||
313 . . . . . . . . . NamePos: -
|
||||
314 . . . . . . . . . Name: "bool"
|
||||
315 . . . . . . . . . Obj: nil
|
||||
316 . . . . . . . . }
|
||||
317 . . . . . . . . Tag: nil
|
||||
318 . . . . . . . . Comment: nil
|
||||
319 . . . . . . . }
|
||||
320 . . . . . . }
|
||||
321 . . . . . . Closing: -
|
||||
322 . . . . . }
|
||||
323 . . . . }
|
||||
324 . . . . Tag: nil
|
||||
325 . . . . Comment: nil
|
||||
326 . . . }
|
||||
327 . . . 4: *ast.Field {
|
||||
328 . . . . Doc: *ast.CommentGroup {
|
||||
329 . . . . . List: []*ast.Comment (len = 1) {
|
||||
330 . . . . . . 0: *ast.Comment {
|
||||
331 . . . . . . . Slash: -
|
||||
332 . . . . . . . Text: "// FileGet is a convenience function that reads a file from the medium."
|
||||
333 . . . . . . }
|
||||
334 . . . . . }
|
||||
335 . . . . }
|
||||
336 . . . . Names: []*ast.Ident (len = 1) {
|
||||
337 . . . . . 0: *ast.Ident {
|
||||
338 . . . . . . NamePos: -
|
||||
339 . . . . . . Name: "FileGet"
|
||||
340 . . . . . . Obj: *ast.Object {
|
||||
341 . . . . . . . Kind: func
|
||||
342 . . . . . . . Name: "FileGet"
|
||||
343 . . . . . . . Decl: *(obj @ 327)
|
||||
344 . . . . . . . Data: nil
|
||||
345 . . . . . . . Type: nil
|
||||
346 . . . . . . }
|
||||
347 . . . . . }
|
||||
348 . . . . }
|
||||
349 . . . . Type: *ast.FuncType {
|
||||
350 . . . . . Func: -
|
||||
351 . . . . . TypeParams: nil
|
||||
352 . . . . . Params: *ast.FieldList {
|
||||
353 . . . . . . Opening: -
|
||||
354 . . . . . . List: []*ast.Field (len = 1) {
|
||||
355 . . . . . . . 0: *ast.Field {
|
||||
356 . . . . . . . . Doc: nil
|
||||
357 . . . . . . . . Names: []*ast.Ident (len = 1) {
|
||||
358 . . . . . . . . . 0: *ast.Ident {
|
||||
359 . . . . . . . . . . NamePos: -
|
||||
360 . . . . . . . . . . Name: "path"
|
||||
361 . . . . . . . . . . Obj: *ast.Object {
|
||||
362 . . . . . . . . . . . Kind: var
|
||||
363 . . . . . . . . . . . Name: "path"
|
||||
364 . . . . . . . . . . . Decl: *(obj @ 355)
|
||||
365 . . . . . . . . . . . Data: nil
|
||||
366 . . . . . . . . . . . Type: nil
|
||||
367 . . . . . . . . . . }
|
||||
368 . . . . . . . . . }
|
||||
369 . . . . . . . . }
|
||||
370 . . . . . . . . Type: *ast.Ident {
|
||||
371 . . . . . . . . . NamePos: -
|
||||
372 . . . . . . . . . Name: "string"
|
||||
373 . . . . . . . . . Obj: nil
|
||||
374 . . . . . . . . }
|
||||
375 . . . . . . . . Tag: nil
|
||||
376 . . . . . . . . Comment: nil
|
||||
377 . . . . . . . }
|
||||
378 . . . . . . }
|
||||
379 . . . . . . Closing: -
|
||||
380 . . . . . }
|
||||
381 . . . . . Results: *ast.FieldList {
|
||||
382 . . . . . . Opening: -
|
||||
383 . . . . . . List: []*ast.Field (len = 2) {
|
||||
384 . . . . . . . 0: *ast.Field {
|
||||
385 . . . . . . . . Doc: nil
|
||||
386 . . . . . . . . Names: nil
|
||||
387 . . . . . . . . Type: *ast.Ident {
|
||||
388 . . . . . . . . . NamePos: -
|
||||
389 . . . . . . . . . Name: "string"
|
||||
390 . . . . . . . . . Obj: nil
|
||||
391 . . . . . . . . }
|
||||
392 . . . . . . . . Tag: nil
|
||||
393 . . . . . . . . Comment: nil
|
||||
394 . . . . . . . }
|
||||
395 . . . . . . . 1: *ast.Field {
|
||||
396 . . . . . . . . Doc: nil
|
||||
397 . . . . . . . . Names: nil
|
||||
398 . . . . . . . . Type: *ast.Ident {
|
||||
399 . . . . . . . . . NamePos: -
|
||||
400 . . . . . . . . . Name: "error"
|
||||
401 . . . . . . . . . Obj: nil
|
||||
402 . . . . . . . . }
|
||||
403 . . . . . . . . Tag: nil
|
||||
404 . . . . . . . . Comment: nil
|
||||
405 . . . . . . . }
|
||||
406 . . . . . . }
|
||||
407 . . . . . . Closing: -
|
||||
408 . . . . . }
|
||||
409 . . . . }
|
||||
410 . . . . Tag: nil
|
||||
411 . . . . Comment: nil
|
||||
412 . . . }
|
||||
413 . . . 5: *ast.Field {
|
||||
414 . . . . Doc: *ast.CommentGroup {
|
||||
415 . . . . . List: []*ast.Comment (len = 1) {
|
||||
416 . . . . . . 0: *ast.Comment {
|
||||
417 . . . . . . . Slash: -
|
||||
418 . . . . . . . Text: "// FileSet is a convenience function that writes a file to the medium."
|
||||
419 . . . . . . }
|
||||
420 . . . . . }
|
||||
421 . . . . }
|
||||
422 . . . . Names: []*ast.Ident (len = 1) {
|
||||
423 . . . . . 0: *ast.Ident {
|
||||
424 . . . . . . NamePos: -
|
||||
425 . . . . . . Name: "FileSet"
|
||||
426 . . . . . . Obj: *ast.Object {
|
||||
427 . . . . . . . Kind: func
|
||||
428 . . . . . . . Name: "FileSet"
|
||||
429 . . . . . . . Decl: *(obj @ 413)
|
||||
430 . . . . . . . Data: nil
|
||||
431 . . . . . . . Type: nil
|
||||
432 . . . . . . }
|
||||
433 . . . . . }
|
||||
434 . . . . }
|
||||
435 . . . . Type: *ast.FuncType {
|
||||
436 . . . . . Func: -
|
||||
437 . . . . . TypeParams: nil
|
||||
438 . . . . . Params: *ast.FieldList {
|
||||
439 . . . . . . Opening: -
|
||||
440 . . . . . . List: []*ast.Field (len = 1) {
|
||||
441 . . . . . . . 0: *ast.Field {
|
||||
442 . . . . . . . . Doc: nil
|
||||
443 . . . . . . . . Names: []*ast.Ident (len = 2) {
|
||||
444 . . . . . . . . . 0: *ast.Ident {
|
||||
445 . . . . . . . . . . NamePos: -
|
||||
446 . . . . . . . . . . Name: "path"
|
||||
447 . . . . . . . . . . Obj: *ast.Object {
|
||||
448 . . . . . . . . . . . Kind: var
|
||||
449 . . . . . . . . . . . Name: "path"
|
||||
450 . . . . . . . . . . . Decl: *(obj @ 441)
|
||||
451 . . . . . . . . . . . Data: nil
|
||||
452 . . . . . . . . . . . Type: nil
|
||||
453 . . . . . . . . . . }
|
||||
454 . . . . . . . . . }
|
||||
455 . . . . . . . . . 1: *ast.Ident {
|
||||
456 . . . . . . . . . . NamePos: -
|
||||
457 . . . . . . . . . . Name: "content"
|
||||
458 . . . . . . . . . . Obj: *ast.Object {
|
||||
459 . . . . . . . . . . . Kind: var
|
||||
460 . . . . . . . . . . . Name: "content"
|
||||
461 . . . . . . . . . . . Decl: *(obj @ 441)
|
||||
462 . . . . . . . . . . . Data: nil
|
||||
463 . . . . . . . . . . . Type: nil
|
||||
464 . . . . . . . . . . }
|
||||
465 . . . . . . . . . }
|
||||
466 . . . . . . . . }
|
||||
467 . . . . . . . . Type: *ast.Ident {
|
||||
468 . . . . . . . . . NamePos: -
|
||||
469 . . . . . . . . . Name: "string"
|
||||
470 . . . . . . . . . Obj: nil
|
||||
471 . . . . . . . . }
|
||||
472 . . . . . . . . Tag: nil
|
||||
473 . . . . . . . . Comment: nil
|
||||
474 . . . . . . . }
|
||||
475 . . . . . . }
|
||||
476 . . . . . . Closing: -
|
||||
477 . . . . . }
|
||||
478 . . . . . Results: *ast.FieldList {
|
||||
479 . . . . . . Opening: -
|
||||
480 . . . . . . List: []*ast.Field (len = 1) {
|
||||
481 . . . . . . . 0: *ast.Field {
|
||||
482 . . . . . . . . Doc: nil
|
||||
483 . . . . . . . . Names: nil
|
||||
484 . . . . . . . . Type: *ast.Ident {
|
||||
485 . . . . . . . . . NamePos: -
|
||||
486 . . . . . . . . . Name: "error"
|
||||
487 . . . . . . . . . Obj: nil
|
||||
488 . . . . . . . . }
|
||||
489 . . . . . . . . Tag: nil
|
||||
490 . . . . . . . . Comment: nil
|
||||
491 . . . . . . . }
|
||||
492 . . . . . . }
|
||||
493 . . . . . . Closing: -
|
||||
494 . . . . . }
|
||||
495 . . . . }
|
||||
496 . . . . Tag: nil
|
||||
497 . . . . Comment: nil
|
||||
498 . . . }
|
||||
499 . . }
|
||||
500 . . Closing: -
|
||||
501 . }
|
||||
502 . Incomplete: false
|
||||
503 }
|
||||
type Medium interface {
|
||||
// Read retrieves the content of a file as a string.
|
||||
Read(path string) (string, error)
|
||||
|
||||
// Write saves the given content to a file, overwriting it if it exists.
|
||||
Write(path, content string) error
|
||||
|
||||
// EnsureDir makes sure a directory exists, creating it if necessary.
|
||||
EnsureDir(path string) error
|
||||
|
||||
// IsFile checks if a path exists and is a regular file.
|
||||
IsFile(path string) bool
|
||||
|
||||
// FileGet is a convenience function that reads a file from the medium.
|
||||
FileGet(path string) (string, error)
|
||||
|
||||
// FileSet is a convenience function that writes a file to the medium.
|
||||
FileSet(path, content string) error
|
||||
}
|
||||
```
|
||||
Medium defines the standard interface for a storage backend.
|
||||
This allows for different implementations (e.g., local disk, S3, SFTP)
|
||||
to be used interchangeably.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### `type MockMedium`
|
||||
|
||||
`MockMedium` implements the `Medium` interface for testing purposes.
|
||||
|
||||
```go
|
||||
type MockMedium 0 *ast.StructType {
|
||||
1 . Struct: -
|
||||
2 . Fields: *ast.FieldList {
|
||||
3 . . Opening: -
|
||||
4 . . List: []*ast.Field (len = 2) {
|
||||
5 . . . 0: *ast.Field {
|
||||
6 . . . . Doc: nil
|
||||
7 . . . . Names: []*ast.Ident (len = 1) {
|
||||
8 . . . . . 0: *ast.Ident {
|
||||
9 . . . . . . NamePos: -
|
||||
10 . . . . . . Name: "Files"
|
||||
11 . . . . . . Obj: *ast.Object {
|
||||
12 . . . . . . . Kind: var
|
||||
13 . . . . . . . Name: "Files"
|
||||
14 . . . . . . . Decl: *(obj @ 5)
|
||||
15 . . . . . . . Data: nil
|
||||
16 . . . . . . . Type: nil
|
||||
17 . . . . . . }
|
||||
18 . . . . . }
|
||||
19 . . . . }
|
||||
20 . . . . Type: *ast.MapType {
|
||||
21 . . . . . Map: -
|
||||
22 . . . . . Key: *ast.Ident {
|
||||
23 . . . . . . NamePos: -
|
||||
24 . . . . . . Name: "string"
|
||||
25 . . . . . . Obj: nil
|
||||
26 . . . . . }
|
||||
27 . . . . . Value: *ast.Ident {
|
||||
28 . . . . . . NamePos: -
|
||||
29 . . . . . . Name: "string"
|
||||
30 . . . . . . Obj: nil
|
||||
31 . . . . . }
|
||||
32 . . . . }
|
||||
33 . . . . Tag: nil
|
||||
34 . . . . Comment: nil
|
||||
35 . . . }
|
||||
36 . . . 1: *ast.Field {
|
||||
37 . . . . Doc: nil
|
||||
38 . . . . Names: []*ast.Ident (len = 1) {
|
||||
39 . . . . . 0: *ast.Ident {
|
||||
40 . . . . . . NamePos: -
|
||||
41 . . . . . . Name: "Dirs"
|
||||
42 . . . . . . Obj: *ast.Object {
|
||||
43 . . . . . . . Kind: var
|
||||
44 . . . . . . . Name: "Dirs"
|
||||
45 . . . . . . . Decl: *(obj @ 36)
|
||||
46 . . . . . . . Data: nil
|
||||
47 . . . . . . . Type: nil
|
||||
48 . . . . . . }
|
||||
49 . . . . . }
|
||||
50 . . . . }
|
||||
51 . . . . Type: *ast.MapType {
|
||||
52 . . . . . Map: -
|
||||
53 . . . . . Key: *ast.Ident {
|
||||
54 . . . . . . NamePos: -
|
||||
55 . . . . . . Name: "string"
|
||||
56 . . . . . . Obj: nil
|
||||
57 . . . . . }
|
||||
58 . . . . . Value: *ast.Ident {
|
||||
59 . . . . . . NamePos: -
|
||||
60 . . . . . . Name: "bool"
|
||||
61 . . . . . . Obj: nil
|
||||
62 . . . . . }
|
||||
63 . . . . }
|
||||
64 . . . . Tag: nil
|
||||
65 . . . . Comment: nil
|
||||
66 . . . }
|
||||
67 . . }
|
||||
68 . . Closing: -
|
||||
69 . }
|
||||
70 . Incomplete: false
|
||||
71 }
|
||||
|
||||
type MockMedium struct {
|
||||
Files map[string]string
|
||||
Dirs map[string]bool
|
||||
}
|
||||
```
|
||||
MockMedium implements the Medium interface for testing purposes.
|
||||
|
||||
|
||||
|
||||
#### Methods
|
||||
|
||||
- `EnsureDir(path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`:
|
||||
|
||||
- `FileGet(path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`:
|
||||
|
||||
- `FileSet(path, content 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`:
|
||||
|
||||
- `IsFile(path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "bool"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`:
|
||||
|
||||
- `Read(path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`:
|
||||
|
||||
- `Write(path, content 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`:
|
||||
|
||||
|
||||
|
||||
|
||||
- `EnsureDir(path string) error`: Mocks creating a directory.
|
||||
- `FileGet(path string) (string, error)`: Mocks reading a file.
|
||||
- `FileSet(path, content string) error`: Mocks writing a file.
|
||||
- `IsFile(path string) bool`: Mocks checking if a path is a file.
|
||||
- `Read(path string) (string, error)`: Mocks reading a file.
|
||||
- `Write(path, content string) error`: Mocks writing a file.
|
||||
|
||||
## Functions
|
||||
|
||||
- `Copy(sourceMedium 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "Medium"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, sourcePath 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, destMedium 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "Medium"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, destPath 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: Copy copies a file from a source medium to a destination medium.
|
||||
- `Copy(sourceMedium Medium, sourcePath string, destMedium Medium, destPath string) error`: Copies a file from a source medium to a destination medium.
|
||||
- `EnsureDir(m Medium, path string) error`: Ensures a directory exists on the given medium.
|
||||
- `IsFile(m Medium, path string) bool`: Checks if a path is a file on the given medium.
|
||||
- `Read(m Medium, path string) (string, error)`: Retrieves the content of a file from the given medium.
|
||||
- `Write(m Medium, path, content string) error`: Saves content to a file on the given medium.
|
||||
|
||||
- `EnsureDir(m 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "Medium"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: EnsureDir ensures a directory exists on the given medium.
|
||||
|
||||
- `IsFile(m 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "Medium"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "bool"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: IsFile checks if a path is a file on the given medium.
|
||||
|
||||
- `Read(m 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "Medium"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: Read retrieves the content of a file from the given medium.
|
||||
|
||||
- `Write(m 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "Medium"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, path, content 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: Write saves content to a file on the given medium.
|
||||
Would you like to see some examples of how to use this service?
|
||||
|
|
|
|||
|
|
@ -3,626 +3,74 @@ title: workspace
|
|||
---
|
||||
# Service: `workspace`
|
||||
|
||||
|
||||
|
||||
|
||||
## Constants
|
||||
|
||||
```godefaultWorkspacelistFile
|
||||
```go
|
||||
defaultWorkspacelistFile
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
## Types
|
||||
|
||||
### `type Options`
|
||||
|
||||
```go
|
||||
type Options 0 *ast.StructType {
|
||||
1 . Struct: -
|
||||
2 . Fields: *ast.FieldList {
|
||||
3 . . Opening: -
|
||||
4 . . List: nil
|
||||
5 . . Closing: -
|
||||
6 . }
|
||||
7 . Incomplete: false
|
||||
8 }
|
||||
|
||||
type Options struct {
|
||||
// Options holds configuration for the workspace service.
|
||||
}
|
||||
```
|
||||
Options holds configuration for the workspace service.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### `type Service`
|
||||
```go
|
||||
type Service 0 *ast.StructType {
|
||||
1 . Struct: -
|
||||
2 . Fields: *ast.FieldList {
|
||||
3 . . Opening: -
|
||||
4 . . List: []*ast.Field (len = 4) {
|
||||
5 . . . 0: *ast.Field {
|
||||
6 . . . . Doc: nil
|
||||
7 . . . . Names: nil
|
||||
8 . . . . Type: *ast.StarExpr {
|
||||
9 . . . . . Star: -
|
||||
10 . . . . . X: *ast.IndexExpr {
|
||||
11 . . . . . . X: *ast.SelectorExpr {
|
||||
12 . . . . . . . X: *ast.Ident {
|
||||
13 . . . . . . . . NamePos: -
|
||||
14 . . . . . . . . Name: "core"
|
||||
15 . . . . . . . . Obj: nil
|
||||
16 . . . . . . . }
|
||||
17 . . . . . . . Sel: *ast.Ident {
|
||||
18 . . . . . . . . NamePos: -
|
||||
19 . . . . . . . . Name: "Runtime"
|
||||
20 . . . . . . . . Obj: nil
|
||||
21 . . . . . . . }
|
||||
22 . . . . . . }
|
||||
23 . . . . . . Lbrack: -
|
||||
24 . . . . . . Index: *ast.Ident {
|
||||
25 . . . . . . . NamePos: -
|
||||
26 . . . . . . . Name: "Options"
|
||||
27 . . . . . . . Obj: *ast.Object {
|
||||
28 . . . . . . . . Kind: type
|
||||
29 . . . . . . . . Name: "Options"
|
||||
30 . . . . . . . . Decl: *ast.TypeSpec {
|
||||
31 . . . . . . . . . Doc: nil
|
||||
32 . . . . . . . . . Name: *ast.Ident {
|
||||
33 . . . . . . . . . . NamePos: -
|
||||
34 . . . . . . . . . . Name: "Options"
|
||||
35 . . . . . . . . . . Obj: *(obj @ 27)
|
||||
36 . . . . . . . . . }
|
||||
37 . . . . . . . . . TypeParams: nil
|
||||
38 . . . . . . . . . Assign: -
|
||||
39 . . . . . . . . . Type: *ast.StructType {
|
||||
40 . . . . . . . . . . Struct: -
|
||||
41 . . . . . . . . . . Fields: *ast.FieldList {
|
||||
42 . . . . . . . . . . . Opening: -
|
||||
43 . . . . . . . . . . . List: nil
|
||||
44 . . . . . . . . . . . Closing: -
|
||||
45 . . . . . . . . . . }
|
||||
46 . . . . . . . . . . Incomplete: false
|
||||
47 . . . . . . . . . }
|
||||
48 . . . . . . . . . Comment: nil
|
||||
49 . . . . . . . . }
|
||||
50 . . . . . . . . Data: nil
|
||||
51 . . . . . . . . Type: nil
|
||||
52 . . . . . . . }
|
||||
53 . . . . . . }
|
||||
54 . . . . . . Rbrack: -
|
||||
55 . . . . . }
|
||||
56 . . . . }
|
||||
57 . . . . Tag: nil
|
||||
58 . . . . Comment: nil
|
||||
59 . . . }
|
||||
60 . . . 1: *ast.Field {
|
||||
61 . . . . Doc: nil
|
||||
62 . . . . Names: []*ast.Ident (len = 1) {
|
||||
63 . . . . . 0: *ast.Ident {
|
||||
64 . . . . . . NamePos: -
|
||||
65 . . . . . . Name: "activeWorkspace"
|
||||
66 . . . . . . Obj: *ast.Object {
|
||||
67 . . . . . . . Kind: var
|
||||
68 . . . . . . . Name: "activeWorkspace"
|
||||
69 . . . . . . . Decl: *(obj @ 60)
|
||||
70 . . . . . . . Data: nil
|
||||
71 . . . . . . . Type: nil
|
||||
72 . . . . . . }
|
||||
73 . . . . . }
|
||||
74 . . . . }
|
||||
75 . . . . Type: *ast.StarExpr {
|
||||
76 . . . . . Star: -
|
||||
77 . . . . . X: *ast.Ident {
|
||||
78 . . . . . . NamePos: -
|
||||
79 . . . . . . Name: "Workspace"
|
||||
80 . . . . . . Obj: *ast.Object {
|
||||
81 . . . . . . . Kind: type
|
||||
82 . . . . . . . Name: "Workspace"
|
||||
83 . . . . . . . Decl: *ast.TypeSpec {
|
||||
84 . . . . . . . . Doc: nil
|
||||
85 . . . . . . . . Name: *ast.Ident {
|
||||
86 . . . . . . . . . NamePos: -
|
||||
87 . . . . . . . . . Name: "Workspace"
|
||||
88 . . . . . . . . . Obj: *(obj @ 80)
|
||||
89 . . . . . . . . }
|
||||
90 . . . . . . . . TypeParams: nil
|
||||
91 . . . . . . . . Assign: -
|
||||
92 . . . . . . . . Type: *ast.StructType {
|
||||
93 . . . . . . . . . Struct: -
|
||||
94 . . . . . . . . . Fields: *ast.FieldList {
|
||||
95 . . . . . . . . . . Opening: -
|
||||
96 . . . . . . . . . . List: []*ast.Field (len = 2) {
|
||||
97 . . . . . . . . . . . 0: *ast.Field {
|
||||
98 . . . . . . . . . . . . Doc: nil
|
||||
99 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) {
|
||||
100 . . . . . . . . . . . . . 0: *ast.Ident {
|
||||
101 . . . . . . . . . . . . . . NamePos: -
|
||||
102 . . . . . . . . . . . . . . Name: "Name"
|
||||
103 . . . . . . . . . . . . . . Obj: *ast.Object {
|
||||
104 . . . . . . . . . . . . . . . Kind: var
|
||||
105 . . . . . . . . . . . . . . . Name: "Name"
|
||||
106 . . . . . . . . . . . . . . . Decl: *(obj @ 97)
|
||||
107 . . . . . . . . . . . . . . . Data: nil
|
||||
108 . . . . . . . . . . . . . . . Type: nil
|
||||
109 . . . . . . . . . . . . . . }
|
||||
110 . . . . . . . . . . . . . }
|
||||
111 . . . . . . . . . . . . }
|
||||
112 . . . . . . . . . . . . Type: *ast.Ident {
|
||||
113 . . . . . . . . . . . . . NamePos: -
|
||||
114 . . . . . . . . . . . . . Name: "string"
|
||||
115 . . . . . . . . . . . . . Obj: nil
|
||||
116 . . . . . . . . . . . . }
|
||||
117 . . . . . . . . . . . . Tag: nil
|
||||
118 . . . . . . . . . . . . Comment: nil
|
||||
119 . . . . . . . . . . . }
|
||||
120 . . . . . . . . . . . 1: *ast.Field {
|
||||
121 . . . . . . . . . . . . Doc: nil
|
||||
122 . . . . . . . . . . . . Names: []*ast.Ident (len = 1) {
|
||||
123 . . . . . . . . . . . . . 0: *ast.Ident {
|
||||
124 . . . . . . . . . . . . . . NamePos: -
|
||||
125 . . . . . . . . . . . . . . Name: "Path"
|
||||
126 . . . . . . . . . . . . . . Obj: *ast.Object {
|
||||
127 . . . . . . . . . . . . . . . Kind: var
|
||||
128 . . . . . . . . . . . . . . . Name: "Path"
|
||||
129 . . . . . . . . . . . . . . . Decl: *(obj @ 120)
|
||||
130 . . . . . . . . . . . . . . . Data: nil
|
||||
131 . . . . . . . . . . . . . . . Type: nil
|
||||
132 . . . . . . . . . . . . . . }
|
||||
133 . . . . . . . . . . . . . }
|
||||
134 . . . . . . . . . . . . }
|
||||
135 . . . . . . . . . . . . Type: *ast.Ident {
|
||||
136 . . . . . . . . . . . . . NamePos: -
|
||||
137 . . . . . . . . . . . . . Name: "string"
|
||||
138 . . . . . . . . . . . . . Obj: nil
|
||||
139 . . . . . . . . . . . . }
|
||||
140 . . . . . . . . . . . . Tag: nil
|
||||
141 . . . . . . . . . . . . Comment: nil
|
||||
142 . . . . . . . . . . . }
|
||||
143 . . . . . . . . . . }
|
||||
144 . . . . . . . . . . Closing: -
|
||||
145 . . . . . . . . . }
|
||||
146 . . . . . . . . . Incomplete: false
|
||||
147 . . . . . . . . }
|
||||
148 . . . . . . . . Comment: nil
|
||||
149 . . . . . . . }
|
||||
150 . . . . . . . Data: nil
|
||||
151 . . . . . . . Type: nil
|
||||
152 . . . . . . }
|
||||
153 . . . . . }
|
||||
154 . . . . }
|
||||
155 . . . . Tag: nil
|
||||
156 . . . . Comment: nil
|
||||
157 . . . }
|
||||
158 . . . 2: *ast.Field {
|
||||
159 . . . . Doc: nil
|
||||
160 . . . . Names: []*ast.Ident (len = 1) {
|
||||
161 . . . . . 0: *ast.Ident {
|
||||
162 . . . . . . NamePos: -
|
||||
163 . . . . . . Name: "workspaceList"
|
||||
164 . . . . . . Obj: *ast.Object {
|
||||
165 . . . . . . . Kind: var
|
||||
166 . . . . . . . Name: "workspaceList"
|
||||
167 . . . . . . . Decl: *(obj @ 158)
|
||||
168 . . . . . . . Data: nil
|
||||
169 . . . . . . . Type: nil
|
||||
170 . . . . . . }
|
||||
171 . . . . . }
|
||||
172 . . . . }
|
||||
173 . . . . Type: *ast.MapType {
|
||||
174 . . . . . Map: -
|
||||
175 . . . . . Key: *ast.Ident {
|
||||
176 . . . . . . NamePos: -
|
||||
177 . . . . . . Name: "string"
|
||||
178 . . . . . . Obj: nil
|
||||
179 . . . . . }
|
||||
180 . . . . . Value: *ast.Ident {
|
||||
181 . . . . . . NamePos: -
|
||||
182 . . . . . . Name: "string"
|
||||
183 . . . . . . Obj: nil
|
||||
184 . . . . . }
|
||||
185 . . . . }
|
||||
186 . . . . Tag: nil
|
||||
187 . . . . Comment: *ast.CommentGroup {
|
||||
188 . . . . . List: []*ast.Comment (len = 1) {
|
||||
189 . . . . . . 0: *ast.Comment {
|
||||
190 . . . . . . . Slash: -
|
||||
191 . . . . . . . Text: "// Maps Workspace ID to Public Key"
|
||||
192 . . . . . . }
|
||||
193 . . . . . }
|
||||
194 . . . . }
|
||||
195 . . . }
|
||||
196 . . . 3: *ast.Field {
|
||||
197 . . . . Doc: nil
|
||||
198 . . . . Names: []*ast.Ident (len = 1) {
|
||||
199 . . . . . 0: *ast.Ident {
|
||||
200 . . . . . . NamePos: -
|
||||
201 . . . . . . Name: "medium"
|
||||
202 . . . . . . Obj: *ast.Object {
|
||||
203 . . . . . . . Kind: var
|
||||
204 . . . . . . . Name: "medium"
|
||||
205 . . . . . . . Decl: *(obj @ 196)
|
||||
206 . . . . . . . Data: nil
|
||||
207 . . . . . . . Type: nil
|
||||
208 . . . . . . }
|
||||
209 . . . . . }
|
||||
210 . . . . }
|
||||
211 . . . . Type: *ast.SelectorExpr {
|
||||
212 . . . . . X: *ast.Ident {
|
||||
213 . . . . . . NamePos: -
|
||||
214 . . . . . . Name: "io"
|
||||
215 . . . . . . Obj: nil
|
||||
216 . . . . . }
|
||||
217 . . . . . Sel: *ast.Ident {
|
||||
218 . . . . . . NamePos: -
|
||||
219 . . . . . . Name: "Medium"
|
||||
220 . . . . . . Obj: nil
|
||||
221 . . . . . }
|
||||
222 . . . . }
|
||||
223 . . . . Tag: nil
|
||||
224 . . . . Comment: nil
|
||||
225 . . . }
|
||||
226 . . }
|
||||
227 . . Closing: -
|
||||
228 . }
|
||||
229 . Incomplete: false
|
||||
230 }
|
||||
|
||||
```go
|
||||
type Service struct {
|
||||
core.Runtime[*Options]
|
||||
activeWorkspace *Workspace
|
||||
workspaceList map[string]string // Maps Workspace ID to Public Key
|
||||
medium io.Medium
|
||||
}
|
||||
```
|
||||
|
||||
Service manages user workspaces.
|
||||
|
||||
|
||||
|
||||
#### Methods
|
||||
|
||||
- `CreateWorkspace(identifier, password 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: CreateWorkspace creates a new, obfuscated workspace on the local medium.
|
||||
|
||||
- `HandleIPCEvents(c 0 *ast.StarExpr {
|
||||
1 . Star: -
|
||||
2 . X: *ast.SelectorExpr {
|
||||
3 . . X: *ast.Ident {
|
||||
4 . . . NamePos: -
|
||||
5 . . . Name: "core"
|
||||
6 . . . Obj: nil
|
||||
7 . . }
|
||||
8 . . Sel: *ast.Ident {
|
||||
9 . . . NamePos: -
|
||||
10 . . . Name: "Core"
|
||||
11 . . . Obj: nil
|
||||
12 . . }
|
||||
13 . }
|
||||
14 }
|
||||
, msg 0 *ast.SelectorExpr {
|
||||
1 . X: *ast.Ident {
|
||||
2 . . NamePos: -
|
||||
3 . . Name: "core"
|
||||
4 . . Obj: nil
|
||||
5 . }
|
||||
6 . Sel: *ast.Ident {
|
||||
7 . . NamePos: -
|
||||
8 . . Name: "Message"
|
||||
9 . . Obj: nil
|
||||
10 . }
|
||||
11 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: HandleIPCEvents processes IPC messages, including injecting dependencies on startup.
|
||||
|
||||
- `ServiceStartup( 0 *ast.SelectorExpr {
|
||||
1 . X: *ast.Ident {
|
||||
2 . . NamePos: -
|
||||
3 . . Name: "context"
|
||||
4 . . Obj: nil
|
||||
5 . }
|
||||
6 . Sel: *ast.Ident {
|
||||
7 . . NamePos: -
|
||||
8 . . Name: "Context"
|
||||
9 . . Obj: nil
|
||||
10 . }
|
||||
11 }
|
||||
, 0 *ast.SelectorExpr {
|
||||
1 . X: *ast.Ident {
|
||||
2 . . NamePos: -
|
||||
3 . . Name: "application"
|
||||
4 . . Obj: nil
|
||||
5 . }
|
||||
6 . Sel: *ast.Ident {
|
||||
7 . . NamePos: -
|
||||
8 . . Name: "ServiceOptions"
|
||||
9 . . Obj: nil
|
||||
10 . }
|
||||
11 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: ServiceStartup initializes the service, loading the workspace list.
|
||||
|
||||
- `SwitchWorkspace(name 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: SwitchWorkspace changes the active workspace.
|
||||
|
||||
- `WorkspaceFileGet(filename 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: WorkspaceFileGet retrieves a file from the active workspace.
|
||||
|
||||
- `WorkspaceFileSet(filename, content 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: WorkspaceFileSet writes a file to the active workspace.
|
||||
|
||||
- `getWorkspaceDir() 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: getWorkspaceDir retrieves the WorkspaceDir from the config service.
|
||||
|
||||
|
||||
- `CreateWorkspace(identifier, password string) (string, error)`: CreateWorkspace creates a new, obfuscated workspace on the local medium.
|
||||
- `HandleIPCEvents(c *core.Core, msg core.Message) error`: HandleIPCEvents processes IPC messages, including injecting dependencies on startup.
|
||||
- `ServiceStartup(context.Context, application.ServiceOptions) error`: ServiceStartup initializes the service, loading the workspace list.
|
||||
- `SwitchWorkspace(name string) error`: SwitchWorkspace changes the active workspace.
|
||||
- `WorkspaceFileGet(filename string) (string, error)`: WorkspaceFileGet retrieves a file from the active workspace.
|
||||
- `WorkspaceFileSet(filename, content string) error`: WorkspaceFileSet writes a file to the active workspace.
|
||||
- `getWorkspaceDir() (string, error)`: getWorkspaceDir retrieves the WorkspaceDir from the config service.
|
||||
|
||||
### `type Workspace`
|
||||
```go
|
||||
type Workspace 0 *ast.StructType {
|
||||
1 . Struct: -
|
||||
2 . Fields: *ast.FieldList {
|
||||
3 . . Opening: -
|
||||
4 . . List: []*ast.Field (len = 2) {
|
||||
5 . . . 0: *ast.Field {
|
||||
6 . . . . Doc: nil
|
||||
7 . . . . Names: []*ast.Ident (len = 1) {
|
||||
8 . . . . . 0: *ast.Ident {
|
||||
9 . . . . . . NamePos: -
|
||||
10 . . . . . . Name: "Name"
|
||||
11 . . . . . . Obj: *ast.Object {
|
||||
12 . . . . . . . Kind: var
|
||||
13 . . . . . . . Name: "Name"
|
||||
14 . . . . . . . Decl: *(obj @ 5)
|
||||
15 . . . . . . . Data: nil
|
||||
16 . . . . . . . Type: nil
|
||||
17 . . . . . . }
|
||||
18 . . . . . }
|
||||
19 . . . . }
|
||||
20 . . . . Type: *ast.Ident {
|
||||
21 . . . . . NamePos: -
|
||||
22 . . . . . Name: "string"
|
||||
23 . . . . . Obj: nil
|
||||
24 . . . . }
|
||||
25 . . . . Tag: nil
|
||||
26 . . . . Comment: nil
|
||||
27 . . . }
|
||||
28 . . . 1: *ast.Field {
|
||||
29 . . . . Doc: nil
|
||||
30 . . . . Names: []*ast.Ident (len = 1) {
|
||||
31 . . . . . 0: *ast.Ident {
|
||||
32 . . . . . . NamePos: -
|
||||
33 . . . . . . Name: "Path"
|
||||
34 . . . . . . Obj: *ast.Object {
|
||||
35 . . . . . . . Kind: var
|
||||
36 . . . . . . . Name: "Path"
|
||||
37 . . . . . . . Decl: *(obj @ 28)
|
||||
38 . . . . . . . Data: nil
|
||||
39 . . . . . . . Type: nil
|
||||
40 . . . . . . }
|
||||
41 . . . . . }
|
||||
42 . . . . }
|
||||
43 . . . . Type: *ast.Ident {
|
||||
44 . . . . . NamePos: -
|
||||
45 . . . . . Name: "string"
|
||||
46 . . . . . Obj: nil
|
||||
47 . . . . }
|
||||
48 . . . . Tag: nil
|
||||
49 . . . . Comment: nil
|
||||
50 . . . }
|
||||
51 . . }
|
||||
52 . . Closing: -
|
||||
53 . }
|
||||
54 . Incomplete: false
|
||||
55 }
|
||||
|
||||
```go
|
||||
type Workspace struct {
|
||||
Name string
|
||||
Path string
|
||||
}
|
||||
```
|
||||
|
||||
Workspace represents a user's workspace.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### `type localMedium`
|
||||
|
||||
```go
|
||||
type localMedium 0 *ast.StructType {
|
||||
1 . Struct: -
|
||||
2 . Fields: *ast.FieldList {
|
||||
3 . . Opening: -
|
||||
4 . . List: nil
|
||||
5 . . Closing: -
|
||||
6 . }
|
||||
7 . Incomplete: false
|
||||
8 }
|
||||
|
||||
type localMedium struct{}
|
||||
```
|
||||
|
||||
localMedium implements the Medium interface for the local disk.
|
||||
|
||||
|
||||
|
||||
#### Methods
|
||||
|
||||
- `EnsureDir(path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: EnsureDir creates a directory on the local disk.
|
||||
|
||||
- `FileGet(path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: FileGet reads a file from the local disk.
|
||||
|
||||
- `FileSet(path, content 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: FileSet writes a file to the local disk.
|
||||
|
||||
- `IsFile(path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "bool"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: IsFile checks if a path exists and is a file on the local disk.
|
||||
|
||||
- `Read(path 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: Read reads a file from the local disk.
|
||||
|
||||
- `Write(path, content 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "string"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: Write writes a file to the local disk.
|
||||
|
||||
|
||||
|
||||
|
||||
- `EnsureDir(path string) error`: EnsureDir creates a directory on the local disk.
|
||||
- `FileGet(path string) (string, error)`: FileGet reads a file from the local disk.
|
||||
- `FileSet(path, content string) error`: FileSet writes a file to the local disk.
|
||||
- `IsFile(path string) bool`: IsFile checks if a path exists and is a file on the local disk.
|
||||
- `Read(path string) (string, error)`: Read reads a file from the local disk.
|
||||
- `Write(path, content string) error`: Write writes a file to the local disk.
|
||||
|
||||
## Functions
|
||||
|
||||
- `NewLocalMedium() 0 *ast.SelectorExpr {
|
||||
1 . X: *ast.Ident {
|
||||
2 . . NamePos: -
|
||||
3 . . Name: "io"
|
||||
4 . . Obj: nil
|
||||
5 . }
|
||||
6 . Sel: *ast.Ident {
|
||||
7 . . NamePos: -
|
||||
8 . . Name: "Medium"
|
||||
9 . . Obj: nil
|
||||
10 . }
|
||||
11 }
|
||||
`: NewLocalMedium creates a new instance of the local storage medium.
|
||||
|
||||
- `Register(c 0 *ast.StarExpr {
|
||||
1 . Star: -
|
||||
2 . X: *ast.SelectorExpr {
|
||||
3 . . X: *ast.Ident {
|
||||
4 . . . NamePos: -
|
||||
5 . . . Name: "core"
|
||||
6 . . . Obj: nil
|
||||
7 . . }
|
||||
8 . . Sel: *ast.Ident {
|
||||
9 . . . NamePos: -
|
||||
10 . . . Name: "Core"
|
||||
11 . . . Obj: nil
|
||||
12 . . }
|
||||
13 . }
|
||||
14 }
|
||||
) 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "any"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
, 0 *ast.Ident {
|
||||
1 . NamePos: -
|
||||
2 . Name: "error"
|
||||
3 . Obj: nil
|
||||
4 }
|
||||
`: Register is the constructor for dynamic dependency injection (used with core.WithService). It creates a Service instance and initializes its core.Runtime field. Dependencies are injected during ServiceStartup.
|
||||
- `NewLocalMedium() io.Medium`: NewLocalMedium creates a new instance of the local storage medium.
|
||||
- `Register(c *core.Core) (any, error)`: Register is the constructor for dynamic dependency injection (used with core.WithService). It creates a Service instance and initializes its core.Runtime field. Dependencies are injected during ServiceStartup.
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"embed"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Core/pkg/core/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
// MockServiceInterface is an interface that MockService implements.
|
||||
type MockServiceInterface interface {
|
||||
GetName() string
|
||||
func TestCore_New_Good(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, c)
|
||||
}
|
||||
|
||||
// MockService is a simple struct to act as a mock service.
|
||||
// Mock service for testing
|
||||
type MockService struct {
|
||||
Name string
|
||||
}
|
||||
|
|
@ -22,166 +24,172 @@ func (m *MockService) GetName() string {
|
|||
return m.Name
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, c)
|
||||
assert.NotNil(t, c.services)
|
||||
assert.False(t, c.servicesLocked)
|
||||
}
|
||||
|
||||
func TestWithService(t *testing.T) {
|
||||
// Test successful service registration
|
||||
t.Run("successful service registration", func(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
|
||||
func TestCore_WithService_Good(t *testing.T) {
|
||||
factory := func(c *Core) (any, error) {
|
||||
return &MockService{Name: "testService"}, nil
|
||||
return &MockService{Name: "test"}, nil
|
||||
}
|
||||
|
||||
err = WithService(factory)(c)
|
||||
c, err := New(WithService(factory))
|
||||
assert.NoError(t, err)
|
||||
|
||||
// The service name is derived from the package path of MockService, which is "core"
|
||||
svc := c.Service("core")
|
||||
assert.NotNil(t, svc)
|
||||
mockSvc, ok := svc.(*MockService)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "testService", mockSvc.Name)
|
||||
})
|
||||
|
||||
// Test service registration with factory error
|
||||
t.Run("service registration with factory error", func(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
|
||||
factory := func(c *Core) (any, error) {
|
||||
return nil, errors.New("factory error")
|
||||
assert.Equal(t, "test", mockSvc.GetName())
|
||||
}
|
||||
|
||||
err = WithService(factory)(c)
|
||||
func TestCore_WithService_Bad(t *testing.T) {
|
||||
factory := func(c *Core) (any, error) {
|
||||
return nil, assert.AnError
|
||||
}
|
||||
_, err := New(WithService(factory))
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "factory error")
|
||||
})
|
||||
assert.ErrorIs(t, err, assert.AnError)
|
||||
}
|
||||
|
||||
// Test service registration when services are locked
|
||||
t.Run("service registration when locked", func(t *testing.T) {
|
||||
func TestCore_WithWails_Good(t *testing.T) {
|
||||
app := &application.App{}
|
||||
c, err := New(WithWails(app))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, app, c.App)
|
||||
}
|
||||
|
||||
//go:embed testdata
|
||||
var testFS embed.FS
|
||||
|
||||
func TestCore_WithAssets_Good(t *testing.T) {
|
||||
c, err := New(WithAssets(testFS))
|
||||
assert.NoError(t, err)
|
||||
assets := c.Assets()
|
||||
file, err := assets.Open("testdata/test.txt")
|
||||
assert.NoError(t, err)
|
||||
defer file.Close()
|
||||
content, err := io.ReadAll(file)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello from testdata\n", string(content))
|
||||
}
|
||||
|
||||
func TestCore_WithServiceLock_Good(t *testing.T) {
|
||||
c, err := New(WithServiceLock())
|
||||
assert.NoError(t, err)
|
||||
|
||||
factory := func(c *Core) (any, error) {
|
||||
return &MockService{Name: "lockedService"}, nil
|
||||
}
|
||||
|
||||
err = WithService(factory)(c)
|
||||
err = c.RegisterService("test", &MockService{})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "is not permitted by the serviceLock setting")
|
||||
})
|
||||
}
|
||||
|
||||
func TestServiceFor(t *testing.T) {
|
||||
func TestCore_RegisterService_Good(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Register a mock service
|
||||
err = c.RegisterService("mockservice", &MockService{Name: "testService"})
|
||||
err = c.RegisterService("test", &MockService{Name: "test"})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test successful retrieval as an interface
|
||||
t.Run("successful retrieval as interface", func(t *testing.T) {
|
||||
svc, err := ServiceFor[MockServiceInterface](c, "mockservice")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "testService", svc.GetName())
|
||||
})
|
||||
|
||||
// Test service not found
|
||||
t.Run("service not found", func(t *testing.T) {
|
||||
_, err := ServiceFor[MockServiceInterface](c, "nonexistent")
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "service 'nonexistent' not found")
|
||||
})
|
||||
|
||||
// Test type mismatch
|
||||
t.Run("type mismatch", func(t *testing.T) {
|
||||
err := c.RegisterService("stringservice", "hello")
|
||||
assert.NoError(t, err)
|
||||
_, err = ServiceFor[MockServiceInterface](c, "stringservice")
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "is of type string, but expected <nil>")
|
||||
})
|
||||
svc := c.Service("test")
|
||||
assert.NotNil(t, svc)
|
||||
mockSvc, ok := svc.(*MockService)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "test", mockSvc.GetName())
|
||||
}
|
||||
|
||||
func TestMustServiceFor(t *testing.T) {
|
||||
func TestCore_RegisterService_Bad(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Register a mock service
|
||||
assert.NoError(t, c.RegisterService("mockservice", &MockService{Name: "testService"}))
|
||||
|
||||
// Test successful retrieval as an interface
|
||||
assert.NotPanics(t, func() {
|
||||
svc := MustServiceFor[MockServiceInterface](c, "mockservice")
|
||||
assert.Equal(t, "testService", svc.GetName())
|
||||
})
|
||||
|
||||
// Test service not found (should panic)
|
||||
assert.Panics(t, func() {
|
||||
MustServiceFor[MockServiceInterface](c, "nonexistent")
|
||||
})
|
||||
|
||||
// Test type mismatch (should panic)
|
||||
assert.NoError(t, c.RegisterService("stringservice", "hello"))
|
||||
assert.Panics(t, func() {
|
||||
MustServiceFor[MockServiceInterface](c, "stringservice")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRegisterService(t *testing.T) {
|
||||
c, err := New()
|
||||
err = c.RegisterService("test", &MockService{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test successful registration
|
||||
err = c.RegisterService("myservice", &MockService{})
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, c.Service("myservice"))
|
||||
|
||||
// Test duplicate registration
|
||||
err = c.RegisterService("myservice", &MockService{})
|
||||
err = c.RegisterService("test", &MockService{})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "already registered")
|
||||
|
||||
// Test empty name
|
||||
err = c.RegisterService("", &MockService{})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "service name cannot be empty")
|
||||
|
||||
// Test registration when locked
|
||||
lockedCore, err := New(WithServiceLock())
|
||||
assert.NoError(t, err)
|
||||
err = lockedCore.RegisterService("lockedservice", &MockService{})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "is not permitted by the serviceLock setting")
|
||||
}
|
||||
|
||||
func TestCoreConfig(t *testing.T) {
|
||||
func TestCore_ServiceFor_Good(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Register a mock config service
|
||||
mockCfg := &testutil.MockConfig{}
|
||||
err = c.RegisterService("config", mockCfg)
|
||||
err = c.RegisterService("test", &MockService{Name: "test"})
|
||||
assert.NoError(t, err)
|
||||
svc, err := ServiceFor[*MockService](c, "test")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "test", svc.GetName())
|
||||
}
|
||||
|
||||
// Test successful retrieval of Config service
|
||||
cfg := c.Config()
|
||||
assert.NotNil(t, cfg)
|
||||
assert.Implements(t, (*Config)(nil), cfg)
|
||||
func TestCore_ServiceFor_Bad(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
_, err = ServiceFor[*MockService](c, "nonexistent")
|
||||
assert.Error(t, err)
|
||||
err = c.RegisterService("test", "not a service")
|
||||
assert.NoError(t, err)
|
||||
_, err = ServiceFor[*MockService](c, "test")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
// Test panic if Config service not registered
|
||||
coreWithoutConfig, err := New()
|
||||
func TestCore_MustServiceFor_Good(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
err = c.RegisterService("test", &MockService{Name: "test"})
|
||||
assert.NoError(t, err)
|
||||
svc := MustServiceFor[*MockService](c, "test")
|
||||
assert.Equal(t, "test", svc.GetName())
|
||||
}
|
||||
|
||||
func TestCore_MustServiceFor_Ugly(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
assert.Panics(t, func() {
|
||||
coreWithoutConfig.Config()
|
||||
MustServiceFor[*MockService](c, "nonexistent")
|
||||
})
|
||||
err = c.RegisterService("test", "not a service")
|
||||
assert.NoError(t, err)
|
||||
assert.Panics(t, func() {
|
||||
MustServiceFor[*MockService](c, "test")
|
||||
})
|
||||
}
|
||||
|
||||
type MockAction struct {
|
||||
handled bool
|
||||
}
|
||||
|
||||
func (a *MockAction) Handle(c *Core, msg Message) error {
|
||||
a.handled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestCore_ACTION_Good(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
action := &MockAction{}
|
||||
c.RegisterAction(action.Handle)
|
||||
err = c.ACTION(nil)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, action.handled)
|
||||
}
|
||||
|
||||
func TestCore_RegisterActions_Good(t *testing.T) {
|
||||
c, err := New()
|
||||
assert.NoError(t, err)
|
||||
action1 := &MockAction{}
|
||||
action2 := &MockAction{}
|
||||
c.RegisterActions(action1.Handle, action2.Handle)
|
||||
err = c.ACTION(nil)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, action1.handled)
|
||||
assert.True(t, action2.handled)
|
||||
}
|
||||
|
||||
func TestCore_WithName_Good(t *testing.T) {
|
||||
factory := func(c *Core) (any, error) {
|
||||
return &MockService{Name: "test"}, nil
|
||||
}
|
||||
c, err := New(WithName("my-service", factory))
|
||||
assert.NoError(t, err)
|
||||
svc := c.Service("my-service")
|
||||
assert.NotNil(t, svc)
|
||||
mockSvc, ok := svc.(*MockService)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "test", mockSvc.GetName())
|
||||
}
|
||||
|
||||
func TestCore_WithName_Bad(t *testing.T) {
|
||||
factory := func(c *Core) (any, error) {
|
||||
return nil, assert.AnError
|
||||
}
|
||||
_, err := New(WithName("my-service", factory))
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, assert.AnError)
|
||||
}
|
||||
|
|
|
|||
87
pkg/io/io_test.go
Normal file
87
pkg/io/io_test.go
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
package io
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIO_Read_Good(t *testing.T) {
|
||||
medium := NewMockMedium()
|
||||
medium.Files["test.txt"] = "hello"
|
||||
|
||||
content, err := Read(medium, "test.txt")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello", content)
|
||||
}
|
||||
|
||||
func TestIO_Read_Bad(t *testing.T) {
|
||||
medium := NewMockMedium()
|
||||
|
||||
_, err := Read(medium, "nonexistent.txt")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestIO_Write_Good(t *testing.T) {
|
||||
medium := NewMockMedium()
|
||||
|
||||
err := Write(medium, "test.txt", "hello")
|
||||
assert.NoError(t, err)
|
||||
|
||||
writtenContent, ok := medium.Files["test.txt"]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "hello", writtenContent)
|
||||
}
|
||||
|
||||
// TODO: The current MockMedium cannot simulate a write error.
|
||||
// func TestIO_Write_Bad(t *testing.T) {
|
||||
// medium := NewMockMedium()
|
||||
// // How to make Write fail?
|
||||
// err := Write(medium, "test.txt", "hello")
|
||||
// assert.Error(t, err)
|
||||
// }
|
||||
|
||||
func TestIO_EnsureDir_Good(t *testing.T) {
|
||||
medium := NewMockMedium()
|
||||
err := EnsureDir(medium, "testdir")
|
||||
assert.NoError(t, err)
|
||||
exists := medium.Dirs["testdir"]
|
||||
assert.True(t, exists)
|
||||
}
|
||||
|
||||
// TODO: The current MockMedium cannot simulate an EnsureDir error.
|
||||
// func TestIO_EnsureDir_Bad(t *testing.T) {
|
||||
// medium := NewMockMedium()
|
||||
// // How to make EnsureDir fail?
|
||||
// err := EnsureDir(medium, "testdir")
|
||||
// assert.Error(t, err)
|
||||
// }
|
||||
|
||||
func TestIO_IsFile_Good(t *testing.T) {
|
||||
medium := NewMockMedium()
|
||||
medium.Files["test.txt"] = "content"
|
||||
assert.True(t, IsFile(medium, "test.txt"))
|
||||
assert.False(t, IsFile(medium, "nonexistent.txt"))
|
||||
}
|
||||
|
||||
func TestIO_Copy_Good(t *testing.T) {
|
||||
source := NewMockMedium()
|
||||
source.Files["source.txt"] = "hello"
|
||||
|
||||
dest := NewMockMedium()
|
||||
|
||||
err := Copy(source, "source.txt", dest, "dest.txt")
|
||||
assert.NoError(t, err)
|
||||
|
||||
copiedContent, ok := dest.Files["dest.txt"]
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "hello", copiedContent)
|
||||
}
|
||||
|
||||
func TestIO_Copy_Bad(t *testing.T) {
|
||||
source := NewMockMedium() // No source file
|
||||
dest := NewMockMedium()
|
||||
|
||||
err := Copy(source, "source.txt", dest, "dest.txt")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package runtime
|
||||
package runtime_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
|
@ -8,67 +8,107 @@ import (
|
|||
"github.com/Snider/Core/pkg/crypt"
|
||||
"github.com/Snider/Core/pkg/display"
|
||||
"github.com/Snider/Core/pkg/help"
|
||||
"github.com/Snider/Core/pkg/i18n"
|
||||
"github.com/Snider/Core/pkg/runtime"
|
||||
"github.com/Snider/Core/pkg/workspace"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
// TestNew ensures that New correctly initializes a Runtime instance.
|
||||
func TestNew(t *testing.T) {
|
||||
// Pass nil for the application, as it is not required for this test.
|
||||
runtime, err := New(nil)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, runtime)
|
||||
|
||||
// Assert that key services are initialized
|
||||
assert.NotNil(t, runtime.Core, "Core service should be initialized")
|
||||
assert.NotNil(t, runtime.Config, "Config service should be initialized")
|
||||
assert.NotNil(t, runtime.Display, "Display service should be initialized")
|
||||
assert.NotNil(t, runtime.Help, "Help service should be initialized")
|
||||
assert.NotNil(t, runtime.Crypt, "Crypt service should be initialized")
|
||||
assert.NotNil(t, runtime.I18n, "I18n service should be initialized")
|
||||
assert.NotNil(t, runtime.Workspace, "Workspace service should be initialized")
|
||||
|
||||
// Verify services are properly wired through Core
|
||||
configFromCore := runtime.Core.Service("config")
|
||||
assert.NotNil(t, configFromCore, "Config should be registered in Core")
|
||||
assert.Equal(t, runtime.Config, configFromCore, "Config from Core should match direct reference")
|
||||
|
||||
displayFromCore := runtime.Core.Service("display")
|
||||
assert.NotNil(t, displayFromCore, "Display should be registered in Core")
|
||||
assert.Equal(t, runtime.Display, displayFromCore, "Display from Core should match direct reference")
|
||||
|
||||
helpFromCore := runtime.Core.Service("help")
|
||||
assert.NotNil(t, helpFromCore, "Help should be registered in Core")
|
||||
assert.Equal(t, runtime.Help, helpFromCore, "Help from Core should match direct reference")
|
||||
|
||||
cryptFromCore := runtime.Core.Service("crypt")
|
||||
assert.NotNil(t, cryptFromCore, "Crypt should be registered in Core")
|
||||
assert.Equal(t, runtime.Crypt, cryptFromCore, "Crypt from Core should match direct reference")
|
||||
|
||||
i18nFromCore := runtime.Core.Service("i18n")
|
||||
assert.NotNil(t, i18nFromCore, "I18n should be registered in Core")
|
||||
assert.Equal(t, runtime.I18n, i18nFromCore, "I18n from Core should match direct reference")
|
||||
|
||||
workspaceFromCore := runtime.Core.Service("workspace")
|
||||
assert.NotNil(t, workspaceFromCore, "Workspace should be registered in Core")
|
||||
assert.Equal(t, runtime.Workspace, workspaceFromCore, "Workspace from Core should match direct reference")
|
||||
testCases := []struct {
|
||||
name string
|
||||
app *application.App
|
||||
factories map[string]runtime.ServiceFactory
|
||||
expectErr bool
|
||||
expectErrStr string
|
||||
checkRuntime func(*testing.T, *runtime.Runtime)
|
||||
}{
|
||||
{
|
||||
name: "Good path",
|
||||
app: nil,
|
||||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return &display.Service{}, nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return &crypt.Service{}, nil },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
},
|
||||
expectErr: false,
|
||||
checkRuntime: func(t *testing.T, rt *runtime.Runtime) {
|
||||
assert.NotNil(t, rt)
|
||||
assert.NotNil(t, rt.Core)
|
||||
assert.NotNil(t, rt.Config)
|
||||
assert.NotNil(t, rt.Display)
|
||||
assert.NotNil(t, rt.Help)
|
||||
assert.NotNil(t, rt.Crypt)
|
||||
assert.NotNil(t, rt.I18n)
|
||||
assert.NotNil(t, rt.Workspace)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Factory returns an error",
|
||||
app: nil,
|
||||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return &display.Service{}, nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return nil, errors.New("crypt service failed") },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
},
|
||||
expectErr: true,
|
||||
expectErrStr: "failed to create service crypt: crypt service failed",
|
||||
},
|
||||
{
|
||||
name: "Factory returns wrong type",
|
||||
app: nil,
|
||||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return "not a display service", nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return &crypt.Service{}, nil },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
},
|
||||
expectErr: true,
|
||||
expectErrStr: "display service has unexpected type",
|
||||
},
|
||||
{
|
||||
name: "With non-nil app",
|
||||
app: &application.App{},
|
||||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return &display.Service{}, nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return &crypt.Service{}, nil },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
},
|
||||
expectErr: false,
|
||||
checkRuntime: func(t *testing.T, rt *runtime.Runtime) {
|
||||
assert.NotNil(t, rt)
|
||||
assert.NotNil(t, rt.Core)
|
||||
assert.NotNil(t, rt.Core.App)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// TestNewServiceInitializationError tests the error path in New.
|
||||
func TestNewServiceInitializationError(t *testing.T) {
|
||||
factories := map[string]ServiceFactory{
|
||||
"config": func() (any, error) { return config.New() },
|
||||
"display": func() (any, error) { return display.New() },
|
||||
"help": func() (any, error) { return help.New() },
|
||||
"crypt": func() (any, error) { return crypt.New() },
|
||||
"i18n": func() (any, error) { return nil, errors.New("i18n service failed to initialize") }, // This factory will fail
|
||||
"workspace": func() (any, error) { return workspace.New() },
|
||||
}
|
||||
|
||||
// Pass nil for the application, as it is not required for this test.
|
||||
runtime, err := NewWithFactories(nil, factories)
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
rt, err := runtime.NewWithFactories(tc.app, tc.factories)
|
||||
|
||||
if tc.expectErr {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, runtime)
|
||||
assert.Contains(t, err.Error(), "failed to create service i18n: i18n service failed to initialize")
|
||||
assert.Contains(t, err.Error(), tc.expectErrStr)
|
||||
assert.Nil(t, rt)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
if tc.checkRuntime != nil {
|
||||
tc.checkRuntime(t, rt)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
196
tdd/core_test.go
196
tdd/core_test.go
|
|
@ -1,196 +0,0 @@
|
|||
package tdd
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Core/pkg/core"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
func TestCore_New_Good(t *testing.T) {
|
||||
c, err := core.New()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, c)
|
||||
}
|
||||
|
||||
// Mock service for testing
|
||||
type MockService struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (m *MockService) GetName() string {
|
||||
return m.Name
|
||||
}
|
||||
|
||||
func TestCore_WithService_Good(t *testing.T) {
|
||||
factory := func(c *core.Core) (any, error) {
|
||||
return &MockService{Name: "test"}, nil
|
||||
}
|
||||
c, err := core.New(core.WithService(factory))
|
||||
assert.NoError(t, err)
|
||||
svc := c.Service("tdd")
|
||||
assert.NotNil(t, svc)
|
||||
mockSvc, ok := svc.(*MockService)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "test", mockSvc.GetName())
|
||||
}
|
||||
|
||||
func TestCore_WithService_Bad(t *testing.T) {
|
||||
factory := func(c *core.Core) (any, error) {
|
||||
return nil, assert.AnError
|
||||
}
|
||||
_, err := core.New(core.WithService(factory))
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, assert.AnError)
|
||||
}
|
||||
|
||||
func TestCore_WithWails_Good(t *testing.T) {
|
||||
app := &application.App{}
|
||||
c, err := core.New(core.WithWails(app))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, app, c.App)
|
||||
}
|
||||
|
||||
//go:embed testdata
|
||||
var testFS embed.FS
|
||||
|
||||
func TestCore_WithAssets_Good(t *testing.T) {
|
||||
c, err := core.New(core.WithAssets(testFS))
|
||||
assert.NoError(t, err)
|
||||
assets := c.Assets()
|
||||
file, err := assets.Open("testdata/test.txt")
|
||||
assert.NoError(t, err)
|
||||
defer file.Close()
|
||||
content, err := io.ReadAll(file)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello from testdata\n", string(content))
|
||||
}
|
||||
|
||||
func TestCore_WithServiceLock_Good(t *testing.T) {
|
||||
c, err := core.New(core.WithServiceLock())
|
||||
assert.NoError(t, err)
|
||||
err = c.RegisterService("test", &MockService{})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCore_RegisterService_Good(t *testing.T) {
|
||||
c, err := core.New()
|
||||
assert.NoError(t, err)
|
||||
err = c.RegisterService("test", &MockService{Name: "test"})
|
||||
assert.NoError(t, err)
|
||||
svc := c.Service("test")
|
||||
assert.NotNil(t, svc)
|
||||
mockSvc, ok := svc.(*MockService)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "test", mockSvc.GetName())
|
||||
}
|
||||
|
||||
func TestCore_RegisterService_Bad(t *testing.T) {
|
||||
c, err := core.New()
|
||||
assert.NoError(t, err)
|
||||
err = c.RegisterService("test", &MockService{})
|
||||
assert.NoError(t, err)
|
||||
err = c.RegisterService("test", &MockService{})
|
||||
assert.Error(t, err)
|
||||
err = c.RegisterService("", &MockService{})
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCore_ServiceFor_Good(t *testing.T) {
|
||||
c, err := core.New()
|
||||
assert.NoError(t, err)
|
||||
err = c.RegisterService("test", &MockService{Name: "test"})
|
||||
assert.NoError(t, err)
|
||||
svc, err := core.ServiceFor[*MockService](c, "test")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "test", svc.GetName())
|
||||
}
|
||||
|
||||
func TestCore_ServiceFor_Bad(t *testing.T) {
|
||||
c, err := core.New()
|
||||
assert.NoError(t, err)
|
||||
_, err = core.ServiceFor[*MockService](c, "nonexistent")
|
||||
assert.Error(t, err)
|
||||
err = c.RegisterService("test", "not a service")
|
||||
assert.NoError(t, err)
|
||||
_, err = core.ServiceFor[*MockService](c, "test")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCore_MustServiceFor_Good(t *testing.T) {
|
||||
c, err := core.New()
|
||||
assert.NoError(t, err)
|
||||
err = c.RegisterService("test", &MockService{Name: "test"})
|
||||
assert.NoError(t, err)
|
||||
svc := core.MustServiceFor[*MockService](c, "test")
|
||||
assert.Equal(t, "test", svc.GetName())
|
||||
}
|
||||
|
||||
func TestCore_MustServiceFor_Ugly(t *testing.T) {
|
||||
c, err := core.New()
|
||||
assert.NoError(t, err)
|
||||
assert.Panics(t, func() {
|
||||
core.MustServiceFor[*MockService](c, "nonexistent")
|
||||
})
|
||||
err = c.RegisterService("test", "not a service")
|
||||
assert.NoError(t, err)
|
||||
assert.Panics(t, func() {
|
||||
core.MustServiceFor[*MockService](c, "test")
|
||||
})
|
||||
}
|
||||
|
||||
type MockAction struct {
|
||||
handled bool
|
||||
}
|
||||
|
||||
func (a *MockAction) Handle(c *core.Core, msg core.Message) error {
|
||||
a.handled = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestCore_ACTION_Good(t *testing.T) {
|
||||
c, err := core.New()
|
||||
assert.NoError(t, err)
|
||||
action := &MockAction{}
|
||||
c.RegisterAction(action.Handle)
|
||||
err = c.ACTION(nil)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, action.handled)
|
||||
}
|
||||
|
||||
func TestCore_RegisterActions_Good(t *testing.T) {
|
||||
c, err := core.New()
|
||||
assert.NoError(t, err)
|
||||
action1 := &MockAction{}
|
||||
action2 := &MockAction{}
|
||||
c.RegisterActions(action1.Handle, action2.Handle)
|
||||
err = c.ACTION(nil)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, action1.handled)
|
||||
assert.True(t, action2.handled)
|
||||
}
|
||||
|
||||
func TestCore_WithName_Good(t *testing.T) {
|
||||
factory := func(c *core.Core) (any, error) {
|
||||
return &MockService{Name: "test"}, nil
|
||||
}
|
||||
c, err := core.New(core.WithName("my-service", factory))
|
||||
assert.NoError(t, err)
|
||||
svc := c.Service("my-service")
|
||||
assert.NotNil(t, svc)
|
||||
mockSvc, ok := svc.(*MockService)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "test", mockSvc.GetName())
|
||||
}
|
||||
|
||||
func TestCore_WithName_Bad(t *testing.T) {
|
||||
factory := func(c *core.Core) (any, error) {
|
||||
return nil, assert.AnError
|
||||
}
|
||||
_, err := core.New(core.WithName("my-service", factory))
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, assert.AnError)
|
||||
}
|
||||
160
tdd/io_test.go
160
tdd/io_test.go
|
|
@ -1,160 +0,0 @@
|
|||
package tdd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Core/pkg/io"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type MockMedium struct {
|
||||
ReadFileFunc func(path string) (string, error)
|
||||
WriteFileFunc func(path, content string) error
|
||||
EnsureDirFunc func(path string) error
|
||||
IsFileFunc func(path string) bool
|
||||
}
|
||||
|
||||
func (m *MockMedium) Read(path string) (string, error) {
|
||||
if m.ReadFileFunc != nil {
|
||||
return m.ReadFileFunc(path)
|
||||
}
|
||||
return "", errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockMedium) Write(path, content string) error {
|
||||
if m.WriteFileFunc != nil {
|
||||
return m.WriteFileFunc(path, content)
|
||||
}
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockMedium) EnsureDir(path string) error {
|
||||
if m.EnsureDirFunc != nil {
|
||||
return m.EnsureDirFunc(path)
|
||||
}
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (m *MockMedium) IsFile(path string) bool {
|
||||
if m.IsFileFunc != nil {
|
||||
return m.IsFileFunc(path)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *MockMedium) FileGet(path string) (string, error) {
|
||||
return m.Read(path)
|
||||
}
|
||||
|
||||
func (m *MockMedium) FileSet(path, content string) error {
|
||||
return m.Write(path, content)
|
||||
}
|
||||
|
||||
func TestIO_Read_Good(t *testing.T) {
|
||||
medium := &MockMedium{
|
||||
ReadFileFunc: func(path string) (string, error) {
|
||||
assert.Equal(t, "test.txt", path)
|
||||
return "hello", nil
|
||||
},
|
||||
}
|
||||
content, err := io.Read(medium, "test.txt")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello", content)
|
||||
}
|
||||
|
||||
func TestIO_Read_Bad(t *testing.T) {
|
||||
medium := &MockMedium{
|
||||
ReadFileFunc: func(path string) (string, error) {
|
||||
return "", assert.AnError
|
||||
},
|
||||
}
|
||||
_, err := io.Read(medium, "test.txt")
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, assert.AnError)
|
||||
}
|
||||
|
||||
func TestIO_Write_Good(t *testing.T) {
|
||||
medium := &MockMedium{
|
||||
WriteFileFunc: func(path, content string) error {
|
||||
assert.Equal(t, "test.txt", path)
|
||||
assert.Equal(t, "hello", content)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
err := io.Write(medium, "test.txt", "hello")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestIO_Write_Bad(t *testing.T) {
|
||||
medium := &MockMedium{
|
||||
WriteFileFunc: func(path, content string) error {
|
||||
return assert.AnError
|
||||
},
|
||||
}
|
||||
err := io.Write(medium, "test.txt", "hello")
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, assert.AnError)
|
||||
}
|
||||
|
||||
func TestIO_EnsureDir_Good(t *testing.T) {
|
||||
medium := &MockMedium{
|
||||
EnsureDirFunc: func(path string) error {
|
||||
assert.Equal(t, "testdir", path)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
err := io.EnsureDir(medium, "testdir")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestIO_EnsureDir_Bad(t *testing.T) {
|
||||
medium := &MockMedium{
|
||||
EnsureDirFunc: func(path string) error {
|
||||
return assert.AnError
|
||||
},
|
||||
}
|
||||
err := io.EnsureDir(medium, "testdir")
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, assert.AnError)
|
||||
}
|
||||
|
||||
func TestIO_IsFile_Good(t *testing.T) {
|
||||
medium := &MockMedium{
|
||||
IsFileFunc: func(path string) bool {
|
||||
assert.Equal(t, "test.txt", path)
|
||||
return true
|
||||
},
|
||||
}
|
||||
assert.True(t, io.IsFile(medium, "test.txt"))
|
||||
}
|
||||
|
||||
func TestIO_Copy_Good(t *testing.T) {
|
||||
source := &MockMedium{
|
||||
ReadFileFunc: func(path string) (string, error) {
|
||||
assert.Equal(t, "source.txt", path)
|
||||
return "hello", nil
|
||||
},
|
||||
}
|
||||
dest := &MockMedium{
|
||||
WriteFileFunc: func(path, content string) error {
|
||||
assert.Equal(t, "dest.txt", path)
|
||||
assert.Equal(t, "hello", content)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
err := io.Copy(source, "source.txt", dest, "dest.txt")
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestIO_Copy_Bad(t *testing.T) {
|
||||
source := &MockMedium{
|
||||
ReadFileFunc: func(path string) (string, error) {
|
||||
return "", assert.AnError
|
||||
},
|
||||
}
|
||||
dest := &MockMedium{}
|
||||
err := io.Copy(source, "source.txt", dest, "dest.txt")
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, assert.AnError)
|
||||
}
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
package tdd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Core/pkg/config"
|
||||
"github.com/Snider/Core/pkg/crypt"
|
||||
"github.com/Snider/Core/pkg/display"
|
||||
"github.com/Snider/Core/pkg/help"
|
||||
"github.com/Snider/Core/pkg/i18n"
|
||||
"github.com/Snider/Core/pkg/runtime"
|
||||
"github.com/Snider/Core/pkg/workspace"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
app *application.App
|
||||
factories map[string]runtime.ServiceFactory
|
||||
expectErr bool
|
||||
expectErrStr string
|
||||
checkRuntime func(*testing.T, *runtime.Runtime)
|
||||
}{
|
||||
{
|
||||
name: "Good path",
|
||||
app: nil,
|
||||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return &display.Service{}, nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return &crypt.Service{}, nil },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
},
|
||||
expectErr: false,
|
||||
checkRuntime: func(t *testing.T, rt *runtime.Runtime) {
|
||||
assert.NotNil(t, rt)
|
||||
assert.NotNil(t, rt.Core)
|
||||
assert.NotNil(t, rt.Config)
|
||||
assert.NotNil(t, rt.Display)
|
||||
assert.NotNil(t, rt.Help)
|
||||
assert.NotNil(t, rt.Crypt)
|
||||
assert.NotNil(t, rt.I18n)
|
||||
assert.NotNil(t, rt.Workspace)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Factory returns an error",
|
||||
app: nil,
|
||||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return &display.Service{}, nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return nil, errors.New("crypt service failed") },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
},
|
||||
expectErr: true,
|
||||
expectErrStr: "failed to create service crypt: crypt service failed",
|
||||
},
|
||||
{
|
||||
name: "Factory returns wrong type",
|
||||
app: nil,
|
||||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return "not a display service", nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return &crypt.Service{}, nil },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
},
|
||||
expectErr: true,
|
||||
expectErrStr: "display service has unexpected type",
|
||||
},
|
||||
{
|
||||
name: "With non-nil app",
|
||||
app: &application.App{},
|
||||
factories: map[string]runtime.ServiceFactory{
|
||||
"config": func() (any, error) { return &config.Service{}, nil },
|
||||
"display": func() (any, error) { return &display.Service{}, nil },
|
||||
"help": func() (any, error) { return &help.Service{}, nil },
|
||||
"crypt": func() (any, error) { return &crypt.Service{}, nil },
|
||||
"i18n": func() (any, error) { return &i18n.Service{}, nil },
|
||||
"workspace": func() (any, error) { return &workspace.Service{}, nil },
|
||||
},
|
||||
expectErr: false,
|
||||
checkRuntime: func(t *testing.T, rt *runtime.Runtime) {
|
||||
assert.NotNil(t, rt)
|
||||
assert.NotNil(t, rt.Core)
|
||||
assert.NotNil(t, rt.Core.App)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
rt, err := runtime.NewWithFactories(tc.app, tc.factories)
|
||||
|
||||
if tc.expectErr {
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tc.expectErrStr)
|
||||
assert.Nil(t, rt)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
if tc.checkRuntime != nil {
|
||||
tc.checkRuntime(t, rt)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue