Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
GOPATH=$(shell go env GOPATH)

.PHONY: test
test:
@echo "==> Running tests"
go test -v ./...
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# lot-sh/core

## Testing

```shell
make test
```
16 changes: 10 additions & 6 deletions resolver_factory.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package core

import "errors"
import (
"errors"

"github.com/lot-sh/core/scheme"
)

// ResolverFactory returns the implementation of Resolver
// which can handle the SchemeType passed as argument
// which can handle the scheme.Type passed as argument
//
// • when there is not a Resolver associated to the SchemeType
// • when there is not a Resolver associated to the scheme.Type
// passed as argument it will return a nil Resolver and an error
func ResolverFactory(st SchemeType) (Resolver, error) {
func ResolverFactory(st scheme.Type) (Resolver, error) {
var resolver Resolver
switch st {
case HTTP, HTTPS:
case scheme.HTTP, scheme.HTTPS:
resolver = &HTTPResolver{}
return resolver, nil
}
return resolver, errors.New("There is not implementation known which supports the given SchemeType")
return resolver, errors.New("There is not implementation known which supports the given scheme.Type")
}
17 changes: 10 additions & 7 deletions resolver_factory_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package core

import "testing"
import (
"testing"
"github.com/lot-sh/core/scheme"
)

func TestResolverFactoryShouldWorksWhenPassedHTTPSchemeType(t *testing.T) {
_, err := ResolverFactory(HTTP)
func TestResolverFactoryShouldWorksWhenPassedHTTPType(t *testing.T) {
_, err := ResolverFactory(scheme.HTTP)
if err != nil {
t.Error("Error should be no returned by ResolverFactory when passed a HTTP SchemeType")
t.Error("Error should be no returned by ResolverFactory when passed a HTTP Type")
}
}

func TestResolverFactoryShouldReturnErrorWhenPassedUNKNOWNSchemeType(t *testing.T) {
_, err := ResolverFactory(UNKNOWN)
func TestResolverFactoryShouldReturnErrorWhenPassedUNKNOWNType(t *testing.T) {
_, err := ResolverFactory(scheme.UNKNOWN)
if err == nil {
t.Error("Error should be returned by ResolverFactory when passed a UNKNONW SchemeType")
t.Error("Error should be returned by ResolverFactory when passed a UNKNONW Type")
}
}
3 changes: 2 additions & 1 deletion resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package core
import (
"fmt"
"io"
"github.com/lot-sh/core/scheme"
)

// Resource struct is the data of the principal resource of
// this application, which is pieces of code and they origin
type Resource struct {
Locator string
Scheme SchemeType
Scheme scheme.Type
}

func (r *Resource) String() string {
Expand Down
67 changes: 67 additions & 0 deletions resource/locator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package resource

import (
"fmt"
"strings"

"github.com/lot-sh/core/scheme"
)

// Locator represents the minimal locator functionality
// For more details visit the RFC
// https://github.com/lot-sh/docs/blob/master/rfcs/002-resource-locator.md
type Locator struct {
scheme scheme.Type
path string
}

// NewLocator instance a locator from a given string which parse
// and ensure if the string is well formated
func NewLocator(strloc string) (*Locator, error) {
res := Locator{}
parts := strings.Split(strloc, scheme.SEPARATOR)
res.scheme = scheme.GetTypeFrom(parts[0])

if res.scheme == scheme.UNKNOWN {
return nil, fmt.Errorf("Failure schema detection when parsing %s", strloc)
}

partsLen := len(parts)
if partsLen != 2 {
if partsLen == 1 {
return nil, fmt.Errorf("Malformatted locator missing path when parsing %s", strloc)
}

return nil, fmt.Errorf("Malformatted locator when parsing %s", strloc)
}

res.path = parts[1]

return &res, nil
}

// Scheme gets the scheme type with string format
func (l *Locator) Scheme() string {
return l.scheme.String()
}

// Path returns the part of the locator wich contains
// the identification of a resource under the specified scheme
func (l *Locator) Path() string {
return l.path
}

// Tag returns the name of version of a resource
func (l *Locator) Tag() string {
parts := strings.Split(l.path, "@")
if len(parts) > 1 {
return parts[1]
}
return ""
}

// String format representation
func (l *Locator) String() string {
s := []string{l.Scheme(), l.Path()}
return strings.Join(s, scheme.SEPARATOR)
}
142 changes: 142 additions & 0 deletions resource/locator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package resource

import (
"fmt"
"strings"
"testing"
)

var suitePassMsg = `
PASS: %s
-> Input: %s`

var suiteFailMsg = `
FAIL: %s
-> Input: %s
-> Actual %s
-> Expected: %s`

func TestLocatorShouldParseAndFormatWithoutErrors(t *testing.T) {
type suiteExpected struct {
scheme string
path string
tag string
}
suites := []struct {
message string
input string
expected suiteExpected
}{
{
"Regular http resource",
"http://example.com/testfile",
suiteExpected{
"http", "//example.com/testfile", "",
},
}, {
"Regular ftp resource",
"ftp://example.com/testfile?test#foo",
suiteExpected{
"ftp", "//example.com/testfile?test#foo", "",
},
}, {
"With tag",
"lot:rubeniskov/semver-patcher@v1.0.1",
suiteExpected{
"lot", "rubeniskov/semver-patcher@v1.0.1", "v1.0.1",
},
}, {
"With ID",
"lot:QmT5NvUtoM5nWFfrQdVrFtvGfKFmG7AHE8P34isapyhCxX",
suiteExpected{
"lot", "QmT5NvUtoM5nWFfrQdVrFtvGfKFmG7AHE8P34isapyhCxX", "",
},
},
}

for _, suite := range suites {
loc, err := NewLocator(suite.input)
if err != nil {
t.Error(err)
}
if loc.Scheme() != suite.expected.scheme {
t.Errorf(
suiteFailMsg,
fmt.Sprintf("%s: Wrong expected scheme", suite.message),
suite.input,
loc.Scheme(),
suite.expected.scheme,
)
}
if loc.Path() != suite.expected.path {
t.Errorf(
suiteFailMsg,
fmt.Sprintf("%s: Wrong expected path", suite.message),
loc.Path(),
suite.expected.path,
)
}
if loc.Tag() != suite.expected.tag {
t.Errorf(
suiteFailMsg,
fmt.Sprintf("%s: Wrong expected tag", suite.message),
loc.Path(),
suite.expected.tag,
)
}
t.Logf(
suitePassMsg,
fmt.Sprintf(
"%s should parse without errors (%s)",
suite.message,
loc,
),
suite.input,
)
}
}

func TestLocatorShouldRaiseErrorScheme(t *testing.T) {
suites := []struct {
message string
input string
expected string
}{
{
"Missing scheme",
"//example.com/testfile",
"Failure schema detection when parsing //example.com/testfile",
}, {
"Wrong scheme",
"scheme:",
"Failure schema detection when parsing scheme:",
}, {
"Missing path",
"ftp",
"Malformatted locator missing path when parsing ftp",
}, {
"Wrong path",
"ftp:test:",
"Malformatted locator when parsing ftp:test:",
},
}

for _, suite := range suites {
_, err := NewLocator(suite.input)
if err == nil {
t.Error(err)
}
if !strings.Contains(err.Error(), suite.expected) {
t.Errorf(suiteFailMsg, suite.message, suite.input, err.Error(), suite.expected)
}
t.Logf(
suitePassMsg,
fmt.Sprintf(
"%s should raise error with the espected message (%s)",
suite.message,
err.Error(),
),
suite.input,
)
}
}
14 changes: 9 additions & 5 deletions resource_factory.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package core

import "errors"
import (
"errors"

"github.com/lot-sh/core/scheme"
)

// ResourceFactory function returns a Resource given a locator
func ResourceFactory(locator string) (Resource, error) {
var scheme SchemeType = GetSchemeTypeFrom(locator)
var sch scheme.Type = scheme.GetTypeFrom(locator)
var resource Resource = Resource{
locator,
scheme,
sch,
}
if scheme == UNKNOWN {
return resource, errors.New("Unknown scheme, the locator may be a invalid one")
if sch == scheme.UNKNOWN {
return resource, errors.New("Unknown scheme.Type, the locator may be a invalid one")
}
return resource, nil
}
9 changes: 6 additions & 3 deletions resource_factory_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package core

import "testing"
import (
"testing"
"github.com/lot-sh/core/scheme"
)

func TestResourceFactoryShouldWorkAsExpected(t *testing.T) {
locator := "lot:QmT5NvUtoM5nWFfrQdVrFtvGfKFmG7AHE8P34isapyhCxX"
resource, err := ResourceFactory(locator)
if err != nil {
t.Error(err)
}
if resource.Scheme != LOT {
t.Errorf("the scheme of %s should be %s, found %s", locator, LOT, resource.Scheme)
if resource.Scheme != scheme.LOT {
t.Errorf("the scheme of %s should be %s, found %s", locator, scheme.LOT, resource.Scheme)
}
if resource.Locator != locator {
t.Errorf("the locator should be %s, found %s", locator, resource.Locator)
Expand Down
Loading