feat: Implement Go encoding types as Sigils
This commit introduces a new `enchantrix` package that provides a flexible and powerful way to transform data using a "Sigil" interface. The package includes implementations for various encoding types (hex, base64, gzip, json) and a comprehensive set of cryptographic hash functions. The `trix` package has been refactored to use the new `enchantrix` package, and its API has been simplified to use string identifiers for Sigils, making it easier to use and decoupling it from the implementation details of the `enchantrix` package. All new functionality is fully tested, and the existing tests have been updated to reflect the API changes.
This commit is contained in:
parent
f88d37cb4a
commit
9dcb399988
8 changed files with 426 additions and 77 deletions
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/crypt"
|
||||
"github.com/Snider/Enchantrix/pkg/crypt/std/chachapoly"
|
||||
"github.com/Snider/Enchantrix/pkg/trix"
|
||||
|
|
@ -20,9 +21,9 @@ func main() {
|
|||
|
||||
// 2. Create a Trix container with the plaintext and attach sigils
|
||||
trixContainer := &trix.Trix{
|
||||
Header: map[string]interface{}{},
|
||||
Payload: plaintext,
|
||||
InSigils: []trix.Sigil{&trix.ReverseSigil{}},
|
||||
Header: map[string]interface{}{},
|
||||
Payload: plaintext,
|
||||
InSigils: []string{"reverse"},
|
||||
}
|
||||
|
||||
// 3. Pack the Trix container to apply the sigil transformations
|
||||
|
|
@ -31,7 +32,6 @@ func main() {
|
|||
}
|
||||
fmt.Printf("Packed (obfuscated) payload: %x\n", trixContainer.Payload)
|
||||
|
||||
|
||||
// 4. Encrypt the packed payload
|
||||
ciphertext, err := chachapoly.Encrypt(trixContainer.Payload, key)
|
||||
if err != nil {
|
||||
|
|
@ -49,7 +49,6 @@ func main() {
|
|||
}
|
||||
trixContainer.ChecksumAlgo = crypt.SHA256
|
||||
|
||||
|
||||
// 6. Encode the .trix container into its binary format
|
||||
magicNumber := "MyT1"
|
||||
encodedTrix, err := trix.Encode(trixContainer, magicNumber)
|
||||
|
|
|
|||
24
pkg/enchantrix/enchantrix.go
Normal file
24
pkg/enchantrix/enchantrix.go
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package enchantrix
|
||||
|
||||
// Sigil defines the interface for a data transformer.
|
||||
type Sigil interface {
|
||||
In(data []byte) ([]byte, error)
|
||||
Out(data []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// Enchantrix defines the interface for acceptance testing.
|
||||
type Enchantrix interface {
|
||||
Transmute(data []byte, sigils []Sigil) ([]byte, error)
|
||||
}
|
||||
|
||||
// Transmute is a helper function for applying a series of sigils to data.
|
||||
func Transmute(data []byte, sigils []Sigil) ([]byte, error) {
|
||||
var err error
|
||||
for _, sigil := range sigils {
|
||||
data, err = sigil.In(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
19
pkg/enchantrix/enchantrix_test.go
Normal file
19
pkg/enchantrix/enchantrix_test.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package enchantrix_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/enchantrix"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTransmute(t *testing.T) {
|
||||
data := []byte("hello")
|
||||
sigils := []enchantrix.Sigil{
|
||||
&enchantrix.ReverseSigil{},
|
||||
&enchantrix.HexSigil{},
|
||||
}
|
||||
result, err := enchantrix.Transmute(data, sigils)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "6f6c6c6568", string(result))
|
||||
}
|
||||
32
pkg/enchantrix/factory_test.go
Normal file
32
pkg/enchantrix/factory_test.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package enchantrix_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/enchantrix"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewSigil(t *testing.T) {
|
||||
t.Run("ValidSigils", func(t *testing.T) {
|
||||
validNames := []string{
|
||||
"reverse", "hex", "base64", "gzip", "json", "json-indent",
|
||||
"md4", "md5", "sha1", "sha224", "sha256", "sha384", "sha512",
|
||||
"ripemd160", "sha3-224", "sha3-256", "sha3-384", "sha3-512",
|
||||
"sha512-224", "sha512-256", "blake2s-256", "blake2b-256",
|
||||
"blake2b-384", "blake2b-512",
|
||||
}
|
||||
for _, name := range validNames {
|
||||
sigil, err := enchantrix.NewSigil(name)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, sigil)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("InvalidSigil", func(t *testing.T) {
|
||||
sigil, err := enchantrix.NewSigil("invalid-sigil-name")
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, sigil)
|
||||
assert.Contains(t, err.Error(), "unknown sigil name")
|
||||
})
|
||||
}
|
||||
240
pkg/enchantrix/sigils.go
Normal file
240
pkg/enchantrix/sigils.go
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
package enchantrix
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
"golang.org/x/crypto/blake2s"
|
||||
"golang.org/x/crypto/md4"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
"golang.org/x/crypto/sha3"
|
||||
)
|
||||
|
||||
// ReverseSigil is a Sigil that reverses the bytes of the payload.
|
||||
type ReverseSigil struct{}
|
||||
|
||||
// In reverses the bytes of the data.
|
||||
func (s *ReverseSigil) In(data []byte) ([]byte, error) {
|
||||
reversed := make([]byte, len(data))
|
||||
for i, j := 0, len(data)-1; i < len(data); i, j = i+1, j-1 {
|
||||
reversed[i] = data[j]
|
||||
}
|
||||
return reversed, nil
|
||||
}
|
||||
|
||||
// Out reverses the bytes of the data.
|
||||
func (s *ReverseSigil) Out(data []byte) ([]byte, error) {
|
||||
return s.In(data)
|
||||
}
|
||||
|
||||
// HexSigil is a Sigil that encodes/decodes data to/from hexadecimal.
|
||||
type HexSigil struct{}
|
||||
|
||||
// In encodes the data to hexadecimal.
|
||||
func (s *HexSigil) In(data []byte) ([]byte, error) {
|
||||
dst := make([]byte, hex.EncodedLen(len(data)))
|
||||
hex.Encode(dst, data)
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// Out decodes the data from hexadecimal.
|
||||
func (s *HexSigil) Out(data []byte) ([]byte, error) {
|
||||
dst := make([]byte, hex.DecodedLen(len(data)))
|
||||
_, err := hex.Decode(dst, data)
|
||||
return dst, err
|
||||
}
|
||||
|
||||
// Base64Sigil is a Sigil that encodes/decodes data to/from base64.
|
||||
type Base64Sigil struct{}
|
||||
|
||||
// In encodes the data to base64.
|
||||
func (s *Base64Sigil) In(data []byte) ([]byte, error) {
|
||||
dst := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
|
||||
base64.StdEncoding.Encode(dst, data)
|
||||
return dst, nil
|
||||
}
|
||||
|
||||
// Out decodes the data from base64.
|
||||
func (s *Base64Sigil) Out(data []byte) ([]byte, error) {
|
||||
dst := make([]byte, base64.StdEncoding.DecodedLen(len(data)))
|
||||
n, err := base64.StdEncoding.Decode(dst, data)
|
||||
return dst[:n], err
|
||||
}
|
||||
|
||||
// GzipSigil is a Sigil that compresses/decompresses data using gzip.
|
||||
type GzipSigil struct{}
|
||||
|
||||
// In compresses the data using gzip.
|
||||
func (s *GzipSigil) In(data []byte) ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
gz := gzip.NewWriter(&b)
|
||||
if _, err := gz.Write(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := gz.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b.Bytes(), nil
|
||||
}
|
||||
|
||||
// Out decompresses the data using gzip.
|
||||
func (s *GzipSigil) Out(data []byte) ([]byte, error) {
|
||||
r, err := gzip.NewReader(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
return io.ReadAll(r)
|
||||
}
|
||||
|
||||
// JSONSigil is a Sigil that compacts or indents JSON data.
|
||||
type JSONSigil struct{ Indent bool }
|
||||
|
||||
// In compacts or indents the JSON data.
|
||||
func (s *JSONSigil) In(data []byte) ([]byte, error) {
|
||||
if s.Indent {
|
||||
var out bytes.Buffer
|
||||
err := json.Indent(&out, data, "", " ")
|
||||
return out.Bytes(), err
|
||||
}
|
||||
var out bytes.Buffer
|
||||
err := json.Compact(&out, data)
|
||||
return out.Bytes(), err
|
||||
}
|
||||
|
||||
// Out is a no-op for JSONSigil.
|
||||
func (s *JSONSigil) Out(data []byte) ([]byte, error) {
|
||||
// For simplicity, Out is a no-op. The primary use is formatting.
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// HashSigil is a Sigil that hashes the data using a specified algorithm.
|
||||
type HashSigil struct {
|
||||
Hash crypto.Hash
|
||||
}
|
||||
|
||||
// NewHashSigil creates a new HashSigil.
|
||||
func NewHashSigil(h crypto.Hash) *HashSigil {
|
||||
return &HashSigil{Hash: h}
|
||||
}
|
||||
|
||||
// In hashes the data.
|
||||
func (s *HashSigil) In(data []byte) ([]byte, error) {
|
||||
var h io.Writer
|
||||
switch s.Hash {
|
||||
case crypto.MD4:
|
||||
h = md4.New()
|
||||
case crypto.MD5:
|
||||
h = md5.New()
|
||||
case crypto.SHA1:
|
||||
h = sha1.New()
|
||||
case crypto.SHA224:
|
||||
h = sha256.New224()
|
||||
case crypto.SHA256:
|
||||
h = sha256.New()
|
||||
case crypto.SHA384:
|
||||
h = sha512.New384()
|
||||
case crypto.SHA512:
|
||||
h = sha512.New()
|
||||
case crypto.RIPEMD160:
|
||||
h = ripemd160.New()
|
||||
case crypto.SHA3_224:
|
||||
h = sha3.New224()
|
||||
case crypto.SHA3_256:
|
||||
h = sha3.New256()
|
||||
case crypto.SHA3_384:
|
||||
h = sha3.New384()
|
||||
case crypto.SHA3_512:
|
||||
h = sha3.New512()
|
||||
case crypto.SHA512_224:
|
||||
h = sha512.New512_224()
|
||||
case crypto.SHA512_256:
|
||||
h = sha512.New512_256()
|
||||
case crypto.BLAKE2s_256:
|
||||
h, _ = blake2s.New256(nil)
|
||||
case crypto.BLAKE2b_256:
|
||||
h, _ = blake2b.New256(nil)
|
||||
case crypto.BLAKE2b_384:
|
||||
h, _ = blake2b.New384(nil)
|
||||
case crypto.BLAKE2b_512:
|
||||
h, _ = blake2b.New512(nil)
|
||||
default:
|
||||
// MD5SHA1 is not supported as a direct hash
|
||||
return nil, errors.New("enchantrix: hash algorithm not available")
|
||||
}
|
||||
|
||||
h.Write(data)
|
||||
return h.(interface{ Sum([]byte) []byte }).Sum(nil), nil
|
||||
}
|
||||
|
||||
// Out is a no-op for HashSigil.
|
||||
func (s *HashSigil) Out(data []byte) ([]byte, error) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// NewSigil is a factory function that returns a Sigil based on a string name.
|
||||
func NewSigil(name string) (Sigil, error) {
|
||||
switch name {
|
||||
case "reverse":
|
||||
return &ReverseSigil{}, nil
|
||||
case "hex":
|
||||
return &HexSigil{}, nil
|
||||
case "base64":
|
||||
return &Base64Sigil{}, nil
|
||||
case "gzip":
|
||||
return &GzipSigil{}, nil
|
||||
case "json":
|
||||
return &JSONSigil{Indent: false}, nil
|
||||
case "json-indent":
|
||||
return &JSONSigil{Indent: true}, nil
|
||||
case "md4":
|
||||
return NewHashSigil(crypto.MD4), nil
|
||||
case "md5":
|
||||
return NewHashSigil(crypto.MD5), nil
|
||||
case "sha1":
|
||||
return NewHashSigil(crypto.SHA1), nil
|
||||
case "sha224":
|
||||
return NewHashSigil(crypto.SHA224), nil
|
||||
case "sha256":
|
||||
return NewHashSigil(crypto.SHA256), nil
|
||||
case "sha384":
|
||||
return NewHashSigil(crypto.SHA384), nil
|
||||
case "sha512":
|
||||
return NewHashSigil(crypto.SHA512), nil
|
||||
case "ripemd160":
|
||||
return NewHashSigil(crypto.RIPEMD160), nil
|
||||
case "sha3-224":
|
||||
return NewHashSigil(crypto.SHA3_224), nil
|
||||
case "sha3-256":
|
||||
return NewHashSigil(crypto.SHA3_256), nil
|
||||
case "sha3-384":
|
||||
return NewHashSigil(crypto.SHA3_384), nil
|
||||
case "sha3-512":
|
||||
return NewHashSigil(crypto.SHA3_512), nil
|
||||
case "sha512-224":
|
||||
return NewHashSigil(crypto.SHA512_224), nil
|
||||
case "sha512-256":
|
||||
return NewHashSigil(crypto.SHA512_256), nil
|
||||
case "blake2s-256":
|
||||
return NewHashSigil(crypto.BLAKE2s_256), nil
|
||||
case "blake2b-256":
|
||||
return NewHashSigil(crypto.BLAKE2b_256), nil
|
||||
case "blake2b-384":
|
||||
return NewHashSigil(crypto.BLAKE2b_384), nil
|
||||
case "blake2b-512":
|
||||
return NewHashSigil(crypto.BLAKE2b_512), nil
|
||||
default:
|
||||
return nil, errors.New("enchantrix: unknown sigil name")
|
||||
}
|
||||
}
|
||||
78
pkg/enchantrix/sigils_test.go
Normal file
78
pkg/enchantrix/sigils_test.go
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package enchantrix_test
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/enchantrix"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestReverseSigil(t *testing.T) {
|
||||
s := &enchantrix.ReverseSigil{}
|
||||
data := []byte("hello")
|
||||
reversed, err := s.In(data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "olleh", string(reversed))
|
||||
original, err := s.Out(reversed)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello", string(original))
|
||||
}
|
||||
|
||||
func TestHexSigil(t *testing.T) {
|
||||
s := &enchantrix.HexSigil{}
|
||||
data := []byte("hello")
|
||||
encoded, err := s.In(data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "68656c6c6f", string(encoded))
|
||||
decoded, err := s.Out(encoded)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello", string(decoded))
|
||||
}
|
||||
|
||||
func TestBase64Sigil(t *testing.T) {
|
||||
s := &enchantrix.Base64Sigil{}
|
||||
data := []byte("hello")
|
||||
encoded, err := s.In(data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "aGVsbG8=", string(encoded))
|
||||
decoded, err := s.Out(encoded)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello", string(decoded))
|
||||
}
|
||||
|
||||
func TestGzipSigil(t *testing.T) {
|
||||
s := &enchantrix.GzipSigil{}
|
||||
data := []byte("hello")
|
||||
compressed, err := s.In(data)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEqual(t, data, compressed)
|
||||
decompressed, err := s.Out(compressed)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "hello", string(decompressed))
|
||||
}
|
||||
|
||||
func TestJSONSigil(t *testing.T) {
|
||||
s := &enchantrix.JSONSigil{Indent: true}
|
||||
data := []byte(`{"hello":"world"}`)
|
||||
indented, err := s.In(data)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "{\n \"hello\": \"world\"\n}", string(indented))
|
||||
s.Indent = false
|
||||
compacted, err := s.In(indented)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `{"hello":"world"}`, string(compacted))
|
||||
}
|
||||
|
||||
func TestHashSigil(t *testing.T) {
|
||||
s := enchantrix.NewHashSigil(crypto.SHA256)
|
||||
data := []byte("hello")
|
||||
hashed, err := s.In(data)
|
||||
assert.NoError(t, err)
|
||||
expectedHash := "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
|
||||
assert.Equal(t, expectedHash, hex.EncodeToString(hashed))
|
||||
unhashed, err := s.Out(hashed)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, hashed, unhashed)
|
||||
}
|
||||
|
|
@ -7,7 +7,9 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/crypt"
|
||||
"github.com/Snider/Enchantrix/pkg/enchantrix"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -22,19 +24,13 @@ var (
|
|||
ErrChecksumMismatch = errors.New("trix: checksum mismatch")
|
||||
)
|
||||
|
||||
// Sigil defines the interface for a data transformer.
|
||||
type Sigil interface {
|
||||
In(data []byte) ([]byte, error)
|
||||
Out(data []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// Trix represents the structure of a .trix file.
|
||||
type Trix struct {
|
||||
Header map[string]interface{}
|
||||
Payload []byte
|
||||
InSigils []Sigil `json:"-"` // Ignore Sigils during JSON marshaling
|
||||
OutSigils []Sigil `json:"-"` // Ignore Sigils during JSON marshaling
|
||||
ChecksumAlgo crypt.HashType `json:"-"`
|
||||
Header map[string]interface{}
|
||||
Payload []byte
|
||||
InSigils []string `json:"-"` // Ignore Sigils during JSON marshaling
|
||||
OutSigils []string `json:"-"` // Ignore Sigils during JSON marshaling
|
||||
ChecksumAlgo crypt.HashType `json:"-"`
|
||||
}
|
||||
|
||||
// Encode serializes a Trix struct into the .trix binary format.
|
||||
|
|
@ -155,11 +151,14 @@ func Decode(data []byte, magicNumber string) (*Trix, error) {
|
|||
|
||||
// Pack applies the In method of all attached sigils to the payload.
|
||||
func (t *Trix) Pack() error {
|
||||
for _, sigil := range t.InSigils {
|
||||
for _, sigilName := range t.InSigils {
|
||||
sigil, err := enchantrix.NewSigil(sigilName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sigil == nil {
|
||||
return ErrNilSigil
|
||||
}
|
||||
var err error
|
||||
t.Payload, err = sigil.In(t.Payload)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -170,16 +169,19 @@ func (t *Trix) Pack() error {
|
|||
|
||||
// Unpack applies the Out method of all sigils in reverse order.
|
||||
func (t *Trix) Unpack() error {
|
||||
sigils := t.OutSigils
|
||||
if len(sigils) == 0 {
|
||||
sigils = t.InSigils
|
||||
sigilNames := t.OutSigils
|
||||
if len(sigilNames) == 0 {
|
||||
sigilNames = t.InSigils
|
||||
}
|
||||
for i := len(sigils) - 1; i >= 0; i-- {
|
||||
sigil := sigils[i]
|
||||
for i := len(sigilNames) - 1; i >= 0; i-- {
|
||||
sigilName := sigilNames[i]
|
||||
sigil, err := enchantrix.NewSigil(sigilName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sigil == nil {
|
||||
return ErrNilSigil
|
||||
}
|
||||
var err error
|
||||
t.Payload, err = sigil.Out(t.Payload)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -187,21 +189,3 @@ func (t *Trix) Unpack() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReverseSigil is an example Sigil that reverses the bytes of the payload.
|
||||
type ReverseSigil struct{}
|
||||
|
||||
// In reverses the bytes of the data.
|
||||
func (s *ReverseSigil) In(data []byte) ([]byte, error) {
|
||||
reversed := make([]byte, len(data))
|
||||
for i, j := 0, len(data)-1; i < len(data); i, j = i+1, j-1 {
|
||||
reversed[i] = data[j]
|
||||
}
|
||||
return reversed, nil
|
||||
}
|
||||
|
||||
// Out reverses the bytes of the data.
|
||||
func (s *ReverseSigil) Out(data []byte) ([]byte, error) {
|
||||
// Reversing the bytes again restores the original data.
|
||||
return s.In(data)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package trix
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/Snider/Enchantrix/pkg/crypt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -115,24 +115,12 @@ func TestTrixEncodeDecode_Ugly(t *testing.T) {
|
|||
|
||||
// --- Sigil Tests ---
|
||||
|
||||
// FailingSigil is a helper for testing sigils that intentionally fail.
|
||||
type FailingSigil struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *FailingSigil) In(data []byte) ([]byte, error) {
|
||||
return nil, s.err
|
||||
}
|
||||
func (s *FailingSigil) Out(data []byte) ([]byte, error) {
|
||||
return nil, s.err
|
||||
}
|
||||
|
||||
func TestPackUnpack_Good(t *testing.T) {
|
||||
originalPayload := []byte("hello world")
|
||||
trix := &Trix{
|
||||
Header: map[string]interface{}{},
|
||||
Payload: originalPayload,
|
||||
InSigils: []Sigil{&ReverseSigil{}, &ReverseSigil{}}, // Double reverse should be original
|
||||
Header: map[string]interface{}{},
|
||||
Payload: originalPayload,
|
||||
InSigils: []string{"reverse", "reverse"}, // Double reverse should be original
|
||||
}
|
||||
|
||||
err := trix.Pack()
|
||||
|
|
@ -145,30 +133,15 @@ func TestPackUnpack_Good(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPackUnpack_Bad(t *testing.T) {
|
||||
expectedErr := errors.New("sigil failed")
|
||||
trix := &Trix{
|
||||
Header: map[string]interface{}{},
|
||||
Payload: []byte("some data"),
|
||||
InSigils: []Sigil{&ReverseSigil{}, &FailingSigil{err: expectedErr}},
|
||||
Header: map[string]interface{}{},
|
||||
Payload: []byte("some data"),
|
||||
InSigils: []string{"reverse", "invalid-sigil-name"},
|
||||
}
|
||||
|
||||
err := trix.Pack()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, expectedErr, err)
|
||||
}
|
||||
|
||||
func TestPackUnpack_Ugly(t *testing.T) {
|
||||
t.Run("NilSigil", func(t *testing.T) {
|
||||
trix := &Trix{
|
||||
Header: map[string]interface{}{},
|
||||
Payload: []byte("some data"),
|
||||
InSigils: []Sigil{nil},
|
||||
}
|
||||
|
||||
err := trix.Pack()
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, ErrNilSigil, err)
|
||||
})
|
||||
assert.Contains(t, err.Error(), "unknown sigil name")
|
||||
}
|
||||
|
||||
// --- Checksum Tests ---
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue