Skip to content
Merged
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
41 changes: 22 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Errors [![Go Report Card](https://goreportcard.com/badge/github.com/neuronlabs/errors)](https://goreportcard.com/report/github.com/neuronlabs/errors) [![GoDoc](https://godoc.org/github.com/neuronlabs/errors?status.svg)](https://godoc.org/github.com/neuronlabs/errors) [![Build Status](https://travis-ci.com/neuronlabs/errors.svg?branch=master)](https://travis-ci.com/neuronlabs/errors) [![Coverage Status](https://coveralls.io/repos/github/neuronlabs/errors/badge.svg?branch=master)](https://coveralls.io/github/neuronlabs/errors?branch=master) ![License](https://img.shields.io/github/license/neuronlabs/errors.svg)

Package errors contains simple golang error handling and classification primitives.
Package errors provides simple golang error and classification primitives.

* [Class](#class)
* [Interfaces](#interfaces)
Expand Down Expand Up @@ -32,7 +32,7 @@ with the same logic but different messages.
A class might be composed in three different ways:

* Major only - the class is Major singleton.
* Major, Minor only - classes that doesn't need triple subclassification divison.
* Major, Minor only - classes that don't need triple subclassification divison.
* Major, Minor, Index - classes that decomposes

Use `NewMajor` or `MustNewMajor` functions to create `Major`, `NewMinor` or `MustNewMinor` for new `Minor` and `NewIndex` or `MustNewIndex` for new `Index`.
Expand Down Expand Up @@ -116,6 +116,7 @@ In order to create detailed error use the `NewDet` or `NewDetf` functions.
import (
"fmt"
"os"

"github.com/neuronlabs/errors"
)

Expand All @@ -129,7 +130,7 @@ func init() {
}

func initClasses() {
inputMjr := errors.NewMajor()
inputMjr := errors.MustNewMajor()
invalidValueMnr := errors.MustNewMinor(inputMjr)
ClInputInvalidValue = errors.MustNewMinorClass(inputMjr, invalidValueMnr)

Expand All @@ -140,25 +141,27 @@ func initClasses() {

func main() {
input, err := getInput()
if err != nil {
classed, ok := err.(errors.ClassError)
if ok {
if classed.Class() == ClInputNotProvided {
fmt.Println("No required integer arguments provided.")
}
if err == nil {
// Everything is fine.
os.Exit(0)
}

if classed, ok := err.(errors.ClassError); ok {
if classed.Class() == ClInputNotProvided {
fmt.Println("No required integer arguments provided.")
os.Exit(1)
}
}

var details string
detailed, ok := err.(errors.DetailedError)
if ok {
details = detailed.Details()
} else {
details = err.Error()
}
fmt.Printf("Invalid input value provided: '%s'\n", details)
os.Exit(1)
var details string
detailed, ok := err.(errors.DetailedError)
if ok {
details = detailed.Details()
} else {
details = err.Error()
}
fmt.Printf("Invalid input value provided: '%s'\n", details)
os.Exit(1)
}


Expand Down Expand Up @@ -202,4 +205,4 @@ func getInput() (int, error) {
## Links

* [Neuron-Core](https://github.com/neuronlabs/neuron-core)
* [Docs](https://docs.neuronlabs.io)
* [Docs](https://docs.neuronlabs.io/errors)
2 changes: 1 addition & 1 deletion class.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func init() {
}

func initClasses() {
internalMajor := container.newMajor()
internalMajor, _ := container.newMajor()

invalidMajor, _ := container.newMinor(internalMajor)
ClInvalidMajor = MustNewMinorClass(internalMajor, invalidMajor)
Expand Down
37 changes: 31 additions & 6 deletions class_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ import (
"testing"
)

// TestNewSubclass tests creation of the `Major` subclassification.
// TestClass tests creation of the `Major` subclassification.
func TestClass(t *testing.T) {
t.Run("Major", func(t *testing.T) {
resetEmptyContainer()

firstMjr := NewMajor()
firstMjr, err := NewMajor()
require.NoError(t, err)
assert.Equal(t, 1, int(firstMjr))

secondMjr := NewMajor()
var secondMjr Major
assert.NotPanics(t, func() { secondMjr = MustNewMajor() })
assert.Equal(t, 2, int(secondMjr))

firstClass, err := NewMajorClass(firstMjr)
Expand All @@ -33,17 +35,28 @@ func TestClass(t *testing.T) {
indexesLen := len(container.indexes)
topMjr := container.major
for i := 0; i < 20; i++ {
NewMajor()
_, err := NewMajor()
require.NoError(t, err)
}
assert.NotEqual(t, minorsLen, len(container.minors))
assert.NotEqual(t, indexesLen, len(container.indexes))
assert.Equal(t, topMjr+20, container.major)

// on testing purpose change top major to max uint8 value.
maxMajor := Major((2 << 7) - 1)
container.major = maxMajor

_, err = NewMajor()
require.Error(t, err)

assert.Panics(t, func() { MustNewMajor() })
})

t.Run("Minor", func(t *testing.T) {
resetEmptyContainer()

mjr := NewMajor()
mjr, err := NewMajor()
require.NoError(t, err)
assert.Equal(t, 1, int(mjr))

mnr1, err := NewMinor(mjr)
Expand Down Expand Up @@ -92,12 +105,18 @@ func TestClass(t *testing.T) {

assert.NotEqual(t, initLen, len(container.indexes[mjr]))

container.minors[mjr] = maxMinorValue
_, err = NewMinor(mjr)
require.Error(t, err)

assert.Panics(t, func() { MustNewMinor(mjr) })
})

t.Run("Index", func(t *testing.T) {
resetEmptyContainer()

mjr := NewMajor()
mjr, err := NewMajor()
require.NoError(t, err)
assert.True(t, mjr.Valid())

mnr, err := NewMinor(mjr)
Expand Down Expand Up @@ -169,6 +188,12 @@ func TestClass(t *testing.T) {
assert.Error(t, err)

assert.Panics(t, func() { MustNewClassWIndex(invMjr, mnr) })

container.indexes[mjr][mnr] = maxIndexValue
_, err = NewIndex(mjr, mnr)

require.Error(t, err)
assert.Panics(t, func() { MustNewIndex(mjr, mnr) })
})
}

Expand Down
14 changes: 12 additions & 2 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@ type classContainer struct {
indexes [][]Index
}

func (c *classContainer) newMajor() Major {
func (c *classContainer) newMajor() (Major, error) {
c.Lock()
defer c.Unlock()

if c.major+1 == 0 {
return 0, New(ClInvalidMajor, "reached maximum number of 'Major' classes")
}
c.major++

c.resizeMinors(c.major)
c.resizeIndexesMajor(c.major)
return c.major
return c.major, nil
}

func (c *classContainer) newMinor(mjr Major) (Minor, error) {
Expand All @@ -36,7 +39,11 @@ func (c *classContainer) newMinor(mjr Major) (Minor, error) {

c.resizeMinors(mjr)

if c.minors[mjr] == maxMinorValue {
return 0, Newf(ClInvalidMinor, "created maximum number of minors for major: '%d'", mjr)
}
c.minors[mjr]++

c.resizeIndexesMinors(mjr, c.minors[mjr])
return c.minors[mjr], nil
}
Expand All @@ -56,6 +63,9 @@ func (c *classContainer) newIndex(mjr Major, mnr Minor) (Index, error) {
c.resizeIndexesMajor(mjr)
c.resizeIndexesMinors(mjr, mnr)

if c.indexes[mjr][mnr] == maxIndexValue {
return 0, Newf(ClInvalidIndex, "reached maximum index subclass number for mjr: '%d', mnr: '%d'", mjr, mnr)
}
c.indexes[mjr][mnr]++
return c.indexes[mjr][mnr], nil
}
Expand Down
12 changes: 11 additions & 1 deletion subclass.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,20 @@ func (m Major) Valid() bool {
}

// NewMajor creates new Major classification.
func NewMajor() Major {
func NewMajor() (Major, error) {
return container.newMajor()
}

// MustNewMajor creates new major error classification.
// Panics if reached maximum number of possible majors.
func MustNewMajor() Major {
mjr, err := container.newMajor()
if err != nil {
panic(err)
}
return mjr
}

// Minor is mid level error subclassification.
// It is a 10 bit long value, which give 2^10 - 1024 - combinations
// for each major.
Expand Down