add interfaces
This commit is contained in:
parent
d3495f874e
commit
06f3247b08
@ -8,8 +8,9 @@ _ "fmt"
|
|||||||
_ "github.com/xeipuuv/gojsonschema"
|
_ "github.com/xeipuuv/gojsonschema"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"io"
|
"io"
|
||||||
_ "log"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
//type JSONDecoder json.Decoder
|
//type JSONDecoder json.Decoder
|
||||||
@ -30,6 +31,10 @@ func NewDecoder(r io.Reader, format Format) Decoder {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewStringDecoder(s string, format Format) Decoder {
|
||||||
|
return NewDecoder(strings.NewReader(s), format)
|
||||||
|
}
|
||||||
|
|
||||||
func NewJSONDecoder(r io.Reader) Decoder {
|
func NewJSONDecoder(r io.Reader) Decoder {
|
||||||
return json.NewDecoder(r)
|
return json.NewDecoder(r)
|
||||||
}
|
}
|
||||||
@ -39,6 +44,7 @@ func NewJSONStringDecoder(s string) Decoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewYAMLDecoder(r io.Reader) Decoder {
|
func NewYAMLDecoder(r io.Reader) Decoder {
|
||||||
|
slog.Info("NewYAMLDecoder()", "reader", r)
|
||||||
return yaml.NewDecoder(r)
|
return yaml.NewDecoder(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +52,17 @@ func NewYAMLStringDecoder(s string) Decoder {
|
|||||||
return yaml.NewDecoder(strings.NewReader(s))
|
return yaml.NewDecoder(strings.NewReader(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProtoBufDecoder(r io.Reader) Decoder {
|
type ProtoDecoder struct {
|
||||||
return nil
|
reader io.Reader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ProtoDecoder) Decode(v any) (err error) {
|
||||||
|
var protoData []byte
|
||||||
|
protoData, err = io.ReadAll(p.reader)
|
||||||
|
err = proto.Unmarshal(protoData, v.(proto.Message))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProtoBufDecoder(r io.Reader) Decoder {
|
||||||
|
return &ProtoDecoder{ reader: r }
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,17 @@ _ "log"
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"github.com/xeipuuv/gojsonschema"
|
"github.com/xeipuuv/gojsonschema"
|
||||||
|
"io"
|
||||||
|
"bytes"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestUser struct {
|
type TestUser struct {
|
||||||
Name string `json:"name" yaml:"name"`
|
Name string `json:"name" yaml:"name" protobuf:"bytes,1,opt,name=name"`
|
||||||
Uid string `json:"uid" yaml:"uid"`
|
Uid string `json:"uid" yaml:"uid" protobuf:"bytes,2,opt,name=uid"`
|
||||||
Group string `json:"group" yaml:"group"`
|
Group string `json:"group" yaml:"group" protobuf:"bytes,3,opt,name=group"`
|
||||||
Home string `json:"home" yaml:"home"`
|
Home string `json:"home" yaml:"home" protobuf:"bytes,4,opt,name=home"`
|
||||||
State string `json:"state" yaml:"state"`
|
State string `json:"state" yaml:"state" protobuf:"bytes,5,opt,name=state"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewYAMLDecoder(t *testing.T) {
|
func TestNewYAMLDecoder(t *testing.T) {
|
||||||
@ -78,3 +81,31 @@ func TestNewJSONStringDecoder(t *testing.T) {
|
|||||||
docErr := e.Decode(&TestUser{})
|
docErr := e.Decode(&TestUser{})
|
||||||
assert.Nil(t, docErr)
|
assert.Nil(t, docErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewDecoder(t *testing.T) {
|
||||||
|
pbData, err := proto.Marshal(&TestUser{ Name: "pb", Uid: "15001", Group: "15005", Home: "/home/pb", State: "present" })
|
||||||
|
assert.Nil(t, err)
|
||||||
|
for _, v := range []struct{ reader io.Reader; format Format; expectedhome string } {
|
||||||
|
{ reader: strings.NewReader(`{
|
||||||
|
"name": "testuser",
|
||||||
|
"uid": "12001",
|
||||||
|
"group": "12001",
|
||||||
|
"home": "/home/testuser",
|
||||||
|
"state": "present" }`), format: FormatJson, expectedhome: "/home/testuser" },
|
||||||
|
{ reader: strings.NewReader(`
|
||||||
|
name: "testuser"
|
||||||
|
uid: "12001"
|
||||||
|
group: "12001"
|
||||||
|
home: "/home/test"
|
||||||
|
state: "present"
|
||||||
|
`), format: FormatYaml, expectedhome: "/home/test" },
|
||||||
|
{ reader: bytes.NewReader(pbData), format: FormatProtoBuf, expectedhome: "/home/pb" },
|
||||||
|
} {
|
||||||
|
|
||||||
|
decoder := NewDecoder(v.reader, v.format)
|
||||||
|
assert.NotNil(t, decoder)
|
||||||
|
u := &TestUser{}
|
||||||
|
assert.Nil(t, decoder.Decode(u))
|
||||||
|
assert.Equal(t, v.expectedhome, u.Home )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -70,6 +70,10 @@ func (f Format) Decoder(r io.Reader) Decoder {
|
|||||||
return NewDecoder(r, f)
|
return NewDecoder(r, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f Format) StringDecoder(s string) Decoder {
|
||||||
|
return NewStringDecoder(s, f)
|
||||||
|
}
|
||||||
|
|
||||||
func (f Format) Serialize(object any, w io.Writer) error {
|
func (f Format) Serialize(object any, w io.Writer) error {
|
||||||
return f.Encoder(w).Encode(object)
|
return f.Encoder(w).Encode(object)
|
||||||
}
|
}
|
||||||
|
10
internal/data/config.go
Normal file
10
internal/data/config.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConfigurationValueGetter interface {
|
||||||
|
GetValue(key string) (any, error)
|
||||||
|
}
|
26
internal/data/converter.go
Normal file
26
internal/data/converter.go
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
)
|
||||||
|
|
||||||
|
// Convert a resource to a document and a document to a resource
|
||||||
|
|
||||||
|
type Emitter interface {
|
||||||
|
Emit(document Document, filter ResourceSelector) (Resource, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Extracter interface {
|
||||||
|
Extract(resource Resource, filter ResourceSelector) (Document, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Converter interface {
|
||||||
|
Typer
|
||||||
|
Emitter
|
||||||
|
Extracter
|
||||||
|
}
|
||||||
|
|
||||||
|
type ManyExtractor interface {
|
||||||
|
ExtractMany(resource Resource, filter ResourceSelector) ([]Document, error)
|
||||||
|
}
|
@ -26,7 +26,7 @@ type Deleter interface {
|
|||||||
Delete(context.Context) error
|
Delete(context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type Crudder struct {
|
type Crudder interface {
|
||||||
Creator
|
Creator
|
||||||
Reader
|
Reader
|
||||||
Updater
|
Updater
|
||||||
|
51
internal/data/document.go
Normal file
51
internal/data/document.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"decl/internal/codec"
|
||||||
|
"io"
|
||||||
|
"decl/internal/mapper"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrEmptyDocument error = errors.New("Document contains no resources")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Serializer interface {
|
||||||
|
JSON() ([]byte, error)
|
||||||
|
YAML() ([]byte, error)
|
||||||
|
PB() ([]byte, error)
|
||||||
|
Generate(w io.Writer) (error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Loader interface {
|
||||||
|
LoadString(string, codec.Format) (error)
|
||||||
|
Load([]byte, codec.Format) (error)
|
||||||
|
LoadReader(io.ReadCloser, codec.Format) (error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DocumentGetter interface {
|
||||||
|
GetDocument() Document
|
||||||
|
}
|
||||||
|
|
||||||
|
type Document interface {
|
||||||
|
Serializer
|
||||||
|
Loader
|
||||||
|
Validator
|
||||||
|
mapper.Mapper
|
||||||
|
|
||||||
|
NewResource(uri string) (Resource, error)
|
||||||
|
Types() (TypesRegistry[Resource])
|
||||||
|
// Resources() []Declaration
|
||||||
|
|
||||||
|
SetConfig(config Document)
|
||||||
|
ConfigDoc() Document
|
||||||
|
Len() int
|
||||||
|
ResolveIds(ctx context.Context)
|
||||||
|
Filter(filter DeclarationSelector) []Declaration
|
||||||
|
|
||||||
|
//Diff(with *Document, output io.Writer) (returnOutput string, diffErr error)
|
||||||
|
}
|
22
internal/data/identifier.go
Normal file
22
internal/data/identifier.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidURI error = errors.New("Invalid URI")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Identifier interface {
|
||||||
|
URI() string
|
||||||
|
SetURI(string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type Selector[Item comparable] func(r Item) bool
|
||||||
|
|
||||||
|
type ResourceSelector Selector[Resource]
|
||||||
|
|
||||||
|
type DeclarationSelector Selector[Declaration]
|
91
internal/data/resource.go
Normal file
91
internal/data/resource.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"decl/internal/mapper"
|
||||||
|
"decl/internal/transport"
|
||||||
|
"gitea.rosskeen.house/rosskeen.house/machine"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidResource error = errors.New("Invalid resource")
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResourceMapper mapper.Map[string, Declaration]
|
||||||
|
|
||||||
|
type StateTransformer interface {
|
||||||
|
Apply() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type Resource interface {
|
||||||
|
Identifier
|
||||||
|
Type() string
|
||||||
|
StateMachine() machine.Stater
|
||||||
|
UseConfig(config ConfigurationValueGetter)
|
||||||
|
ResolveId(context.Context) string
|
||||||
|
Loader
|
||||||
|
StateTransformer
|
||||||
|
Crudder
|
||||||
|
Validator
|
||||||
|
Clone() Resource
|
||||||
|
SetResourceMapper(ResourceMapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Declaration interface {
|
||||||
|
Identifier
|
||||||
|
ResourceType() TypeName
|
||||||
|
ResolveId(context.Context) string
|
||||||
|
Loader
|
||||||
|
Validator
|
||||||
|
StateTransformer
|
||||||
|
Resource() Resource
|
||||||
|
Clone() Declaration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewResourceMapper() ResourceMapper {
|
||||||
|
return mapper.New[string, Declaration]()
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContentIdentifier interface {
|
||||||
|
ContentType() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContentReader interface {
|
||||||
|
ContentReaderStream() (*transport.Reader, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContentWriter interface {
|
||||||
|
ContentWriterStream() (*transport.Writer, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContentReadWriter interface {
|
||||||
|
ContentReader
|
||||||
|
ContentWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContentGetter interface {
|
||||||
|
GetContent(w io.Writer) (contentReader io.ReadCloser, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContentSetter interface {
|
||||||
|
SetContent(r io.Reader) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContentGetSetter interface {
|
||||||
|
ContentGetter
|
||||||
|
ContentSetter
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileResource interface {
|
||||||
|
FilePath() string
|
||||||
|
SetFileInfo(fs.FileInfo) error
|
||||||
|
FileInfo() fs.FileInfo
|
||||||
|
ContentGetSetter
|
||||||
|
SetContentSourceRef(uri string)
|
||||||
|
}
|
||||||
|
|
50
internal/data/stater.go
Normal file
50
internal/data/stater.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gitea.rosskeen.house/rosskeen.house/machine"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StorageMachine(sub machine.Subscriber) machine.Stater {
|
||||||
|
// start_destroy -> absent -> start_create -> present -> start_destroy
|
||||||
|
stater := machine.New("unknown")
|
||||||
|
stater.AddStates("initialized", "unkonwn", "absent", "start_create", "present", "start_delete", "start_read", "start_update")
|
||||||
|
stater.AddTransition("construct", machine.States("unknown"), "initialized")
|
||||||
|
stater.AddTransition("create", machine.States("unknown", "initialized", "absent"), "start_create")
|
||||||
|
if e := stater.AddSubscription("create", sub); e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stater.AddTransition("created", machine.States("start_create"), "present")
|
||||||
|
if e := stater.AddSubscription("created", sub); e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stater.AddTransition("exists", machine.States("unknown", "initialized", "absent"), "present")
|
||||||
|
if e := stater.AddSubscription("exists", sub); e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stater.AddTransition("notexists", machine.States("*"), "absent")
|
||||||
|
if e := stater.AddSubscription("notexists", sub); e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stater.AddTransition("read", machine.States("*"), "start_read")
|
||||||
|
if e := stater.AddSubscription("read", sub); e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stater.AddTransition("state_read", machine.States("start_read"), "present")
|
||||||
|
stater.AddTransition("update", machine.States("*"), "start_update")
|
||||||
|
if e := stater.AddSubscription("update", sub); e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stater.AddTransition("updated", machine.States("start_update"), "present")
|
||||||
|
stater.AddTransition("delete", machine.States("*"), "start_delete")
|
||||||
|
if e := stater.AddSubscription("delete", sub); e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
stater.AddTransition("deleted", machine.States("start_delete"), "absent")
|
||||||
|
if e := stater.AddSubscription("deleted", sub); e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return stater
|
||||||
|
}
|
||||||
|
|
23
internal/data/types.go
Normal file
23
internal/data/types.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Factory[Product comparable] func(*url.URL) Product
|
||||||
|
|
||||||
|
type TypesRegistry[Product comparable] interface {
|
||||||
|
New(uri string) (result Product, err error)
|
||||||
|
Has(typename string) bool
|
||||||
|
//Get(string) Factory[Product]
|
||||||
|
}
|
||||||
|
|
||||||
|
type TypeName string //`json:"type"`
|
||||||
|
|
||||||
|
func (t TypeName) String() string { return string(t) }
|
||||||
|
|
||||||
|
type Typer interface {
|
||||||
|
Type() TypeName
|
||||||
|
}
|
64
internal/folio/uri.go
Normal file
64
internal/folio/uri.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package folio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"decl/internal/transport"
|
||||||
|
"decl/internal/data"
|
||||||
|
"decl/internal/identifier"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidURI error = errors.New("Invalid URI")
|
||||||
|
)
|
||||||
|
|
||||||
|
type URI identifier.ID
|
||||||
|
|
||||||
|
func (u URI) NewResource(document data.Document) (newResource data.Resource, err error) {
|
||||||
|
if document == nil {
|
||||||
|
declaration := NewDeclaration()
|
||||||
|
if err = declaration.NewResource((*string)(&u)); err == nil {
|
||||||
|
return declaration.Attributes.(data.Resource), err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newResource, err = document.NewResource(string(u))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u URI) Parse() *url.URL {
|
||||||
|
url, e := url.Parse(string(u))
|
||||||
|
if e == nil {
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u URI) Exists() bool {
|
||||||
|
return transport.ExistsURI(string(u))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u URI) ContentReaderStream() (*transport.Reader, error) {
|
||||||
|
return transport.NewReaderURI(string(u))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u URI) ContentWriterStream() (*transport.Writer, error) {
|
||||||
|
return transport.NewWriterURI(string(u))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u URI) String() string {
|
||||||
|
return string(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *URI) SetURL(url *url.URL) {
|
||||||
|
(*identifier.ID)(u).SetURL(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u URI) Extension() (string, string) {
|
||||||
|
return (identifier.ID)(u).Extension()
|
||||||
|
}
|
||||||
|
|
16
internal/folio/uri_test.go
Normal file
16
internal/folio/uri_test.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package folio
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestURI(t *testing.T) {
|
||||||
|
var file URI = URI(fmt.Sprintf("file://%s", TempDir))
|
||||||
|
u := file.Parse()
|
||||||
|
assert.Equal(t, "file", u.Scheme)
|
||||||
|
assert.True(t, file.Exists())
|
||||||
|
}
|
42
internal/identifier/id.go
Normal file
42
internal/identifier/id.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package identifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidURI error = errors.New("Invalid URI")
|
||||||
|
)
|
||||||
|
|
||||||
|
type ID string
|
||||||
|
|
||||||
|
func (i *ID) SetURL(u *url.URL) {
|
||||||
|
*i = ID(u.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i ID) Parse() *url.URL {
|
||||||
|
url, e := url.Parse(string(i))
|
||||||
|
if e == nil {
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i ID) Extension() (exttype string, fileext string) {
|
||||||
|
elements := strings.Split(string(i), ".")
|
||||||
|
numberOfElements := len(elements)
|
||||||
|
if numberOfElements > 1 {
|
||||||
|
if numberOfElements > 2 {
|
||||||
|
exttype = elements[numberOfElements - 2]
|
||||||
|
fileext = elements[numberOfElements - 1]
|
||||||
|
}
|
||||||
|
exttype = elements[numberOfElements - 1]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
44
internal/identifier/id_test.go
Normal file
44
internal/identifier/id_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
||||||
|
|
||||||
|
package identifier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var TempDir string
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
var err error
|
||||||
|
TempDir, err = os.MkdirTemp("", "testidentifier")
|
||||||
|
if err != nil || TempDir == "" {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rc := m.Run()
|
||||||
|
|
||||||
|
os.RemoveAll(TempDir)
|
||||||
|
os.Exit(rc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestID(t *testing.T) {
|
||||||
|
var file ID = ID(fmt.Sprintf("file://%s", TempDir))
|
||||||
|
u := file.Parse()
|
||||||
|
assert.Equal(t, "file", u.Scheme)
|
||||||
|
filetype, fileext := file.Extension()
|
||||||
|
assert.Equal(t, "", filetype)
|
||||||
|
assert.Equal(t, "", fileext)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetID(t *testing.T) {
|
||||||
|
var file ID = ID(fmt.Sprintf("file://%s", TempDir))
|
||||||
|
u := file.Parse()
|
||||||
|
|
||||||
|
var setFile ID
|
||||||
|
setFile.SetURL(u)
|
||||||
|
assert.Equal(t, file, setFile)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user