aboutsummaryrefslogtreecommitdiff
path: root/object
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-04-02 07:51:14 +0000
committerGravatar Runxi Yu2026-04-02 07:53:36 +0000
commit1013f61420d39fe491bd1e1af613c601dc5c3137 (patch)
tree3171754f4404916b04d8f08b77bc629af51cefab /object
parentobject/id: Add algorithm tests (diff)
signatureNo signature
ci: Stricter linting
Diffstat (limited to 'object')
-rw-r--r--object/id/algorithm_details.go28
-rw-r--r--object/id/algorithm_ops.go14
-rw-r--r--object/id/algorithm_test.go115
-rw-r--r--object/id/object_id_test.go122
4 files changed, 153 insertions, 126 deletions
diff --git a/object/id/algorithm_details.go b/object/id/algorithm_details.go
index d3fd665d..23737ab5 100644
--- a/object/id/algorithm_details.go
+++ b/object/id/algorithm_details.go
@@ -16,26 +16,46 @@ type algorithmDetails struct {
emptyTree ObjectID
}
-func (algo Algorithm) info() algorithmDetails {
+func (algo Algorithm) details() algorithmDetails {
return algorithmTable[algo]
}
//nolint:gochecknoglobals
var algorithmTable = [...]algorithmDetails{
- AlgorithmUnknown: {},
+ AlgorithmUnknown: {}, //nolint:exhaustruct
AlgorithmSHA1: {
name: "sha1",
size: sha1.Size,
packHashID: 1,
signatureHeaderName: "gpgsig",
- new: sha1.New,
+ sum: func(data []byte) ObjectID {
+ sum := sha1.Sum(data) //#nosec G401
+
+ var id ObjectID
+ copy(id.data[:], sum[:])
+ id.algo = AlgorithmSHA1
+
+ return id
+ },
+ new: sha1.New,
+ emptyTree: ObjectID{}, //nolint:exhaustruct
},
AlgorithmSHA256: {
name: "sha256",
size: sha256.Size,
packHashID: 2,
signatureHeaderName: "gpgsig-sha256",
- new: sha256.New,
+ sum: func(data []byte) ObjectID {
+ sum := sha256.Sum256(data)
+
+ var id ObjectID
+ copy(id.data[:], sum[:])
+ id.algo = AlgorithmSHA256
+
+ return id
+ },
+ new: sha256.New,
+ emptyTree: ObjectID{}, //nolint:exhaustruct
},
}
diff --git a/object/id/algorithm_ops.go b/object/id/algorithm_ops.go
index b746dc5f..01d26c08 100644
--- a/object/id/algorithm_ops.go
+++ b/object/id/algorithm_ops.go
@@ -6,7 +6,7 @@ import "hash"
// an empty tree ("tree 0\x00")
// for this algorithm.
func (algo Algorithm) EmptyTree() ObjectID {
- return algo.info().emptyTree
+ return algo.details().emptyTree
}
// HexLen returns the encoded hexadecimal length.
@@ -16,12 +16,12 @@ func (algo Algorithm) HexLen() int {
// Size returns the hash size in bytes.
func (algo Algorithm) Size() int {
- return algo.info().size
+ return algo.details().size
}
// New returns a new hash.Hash for this algorithm.
func (algo Algorithm) New() (hash.Hash, error) {
- newFn := algo.info().new
+ newFn := algo.details().new
if newFn == nil {
return nil, ErrInvalidAlgorithm
}
@@ -33,22 +33,22 @@ func (algo Algorithm) New() (hash.Hash, error) {
//
// Unknown algorithms return 0.
func (algo Algorithm) PackHashID() uint32 {
- return algo.info().packHashID
+ return algo.details().packHashID
}
// SignatureHeaderName returns the signature header name for this algorithm.
func (algo Algorithm) SignatureHeaderName() string {
- return algo.info().signatureHeaderName
+ return algo.details().signatureHeaderName
}
// String returns the canonical algorithm name.
func (algo Algorithm) String() string {
- return algo.info().name
+ return algo.details().name
}
// Sum computes an object ID from raw data using the selected algorithm.
func (algo Algorithm) Sum(data []byte) ObjectID {
- return algo.info().sum(data)
+ return algo.details().sum(data)
}
// Zero returns the all-zero object ID for this algorithm.
diff --git a/object/id/algorithm_test.go b/object/id/algorithm_test.go
index 17d86805..15f61ecb 100644
--- a/object/id/algorithm_test.go
+++ b/object/id/algorithm_test.go
@@ -1,8 +1,6 @@
package id_test
import (
- "bytes"
- "strings"
"testing"
"codeberg.org/lindenii/furgit/object/id"
@@ -59,119 +57,6 @@ func TestParseAlgorithm(t *testing.T) {
}
}
-func TestFromHexRoundtrip(t *testing.T) {
- t.Parallel()
-
- for _, algo := range id.SupportedAlgorithms() {
- t.Run(algo.String(), func(t *testing.T) {
- t.Parallel()
-
- hex := strings.Repeat("01", algo.Size())
-
- i, err := id.FromHex(algo, hex)
- if err != nil {
- t.Fatalf("FromHex failed: %v", err)
- }
-
- if got := i.String(); got != hex {
- t.Fatalf("String() = %q, want %q", got, hex)
- }
-
- if got := i.Algorithm().Size(); got != algo.Size() {
- t.Fatalf("Size() = %d, want %d", got, algo.Size())
- }
-
- raw := i.Bytes()
- if len(raw) != algo.Size() {
- t.Fatalf("Bytes len = %d, want %d", len(raw), algo.Size())
- }
-
- id2, err := id.FromBytes(algo, raw)
- if err != nil {
- t.Fatalf("FromBytes failed: %v", err)
- }
-
- if id2.String() != hex {
- t.Fatalf("FromBytes roundtrip = %q, want %q", id2.String(), hex)
- }
- })
- }
-}
-
-func TestFromHexErrors(t *testing.T) {
- t.Parallel()
-
- t.Run("unknown algo", func(t *testing.T) {
- t.Parallel()
-
- _, err := id.FromHex(id.AlgorithmUnknown, "00")
- if err == nil {
- t.Fatalf("expected FromHex error")
- }
- })
- // TODO: This may need to be revisited when hash-function-transition is implemented.
-
- for _, algo := range id.SupportedAlgorithms() {
- t.Run(algo.String(), func(t *testing.T) {
- t.Parallel()
-
- _, err := id.FromHex(algo, strings.Repeat("0", algo.HexLen()-1))
- if err == nil {
- t.Fatalf("expected FromHex odd-len error")
- }
-
- _, err = id.FromHex(algo, strings.Repeat("0", algo.HexLen()-2))
- if err == nil {
- t.Fatalf("expected FromHex wrong-len error")
- }
-
- _, err = id.FromHex(algo, "z"+strings.Repeat("0", algo.HexLen()-1))
- if err == nil {
- t.Fatalf("expected FromHex invalid-hex error")
- }
- })
- }
-}
-
-func TestFromBytesErrors(t *testing.T) {
- t.Parallel()
-
- _, err := id.FromBytes(id.AlgorithmUnknown, []byte{1, 2})
- if err == nil {
- t.Fatalf("expected FromBytes unknown algo error")
- }
-
- for _, algo := range id.SupportedAlgorithms() {
- _, err = id.FromBytes(algo, []byte{1, 2})
- if err == nil {
- t.Fatalf("expected FromBytes wrong size error")
- }
- }
-}
-
-func TestBytesReturnsCopy(t *testing.T) {
- t.Parallel()
-
- for _, algo := range id.SupportedAlgorithms() {
- id, err := id.FromHex(algo, strings.Repeat("01", algo.Size()))
- if err != nil {
- t.Fatalf("ParseHex failed: %v", err)
- }
-
- b1 := id.Bytes()
-
- b2 := id.Bytes()
- if !bytes.Equal(b1, b2) {
- t.Fatalf("Bytes mismatch")
- }
-
- b1[0] ^= 0xff
- if bytes.Equal(b1, b2) {
- t.Fatalf("Bytes should return independent copies")
- }
- }
-}
-
func TestAlgorithmSum(t *testing.T) {
t.Parallel()
diff --git a/object/id/object_id_test.go b/object/id/object_id_test.go
new file mode 100644
index 00000000..ba9413ba
--- /dev/null
+++ b/object/id/object_id_test.go
@@ -0,0 +1,122 @@
+package id_test
+
+import (
+ "bytes"
+ "strings"
+ "testing"
+
+ "codeberg.org/lindenii/furgit/object/id"
+)
+
+func TestFromBytesErrors(t *testing.T) {
+ t.Parallel()
+
+ _, err := id.FromBytes(id.AlgorithmUnknown, []byte{1, 2})
+ if err == nil {
+ t.Fatalf("expected FromBytes unknown algo error")
+ }
+
+ for _, algo := range id.SupportedAlgorithms() {
+ _, err = id.FromBytes(algo, []byte{1, 2})
+ if err == nil {
+ t.Fatalf("expected FromBytes wrong size error")
+ }
+ }
+}
+
+func TestBytesReturnsCopy(t *testing.T) {
+ t.Parallel()
+
+ for _, algo := range id.SupportedAlgorithms() {
+ id, err := id.FromHex(algo, strings.Repeat("01", algo.Size()))
+ if err != nil {
+ t.Fatalf("ParseHex failed: %v", err)
+ }
+
+ b1 := id.Bytes()
+
+ b2 := id.Bytes()
+ if !bytes.Equal(b1, b2) {
+ t.Fatalf("Bytes mismatch")
+ }
+
+ b1[0] ^= 0xff
+ if bytes.Equal(b1, b2) {
+ t.Fatalf("Bytes should return independent copies")
+ }
+ }
+}
+
+func TestFromHexErrors(t *testing.T) {
+ t.Parallel()
+
+ t.Run("unknown algo", func(t *testing.T) {
+ t.Parallel()
+
+ _, err := id.FromHex(id.AlgorithmUnknown, "00")
+ if err == nil {
+ t.Fatalf("expected FromHex error")
+ }
+ })
+ // TODO: This may need to be revisited when hash-function-transition is implemented.
+
+ for _, algo := range id.SupportedAlgorithms() {
+ t.Run(algo.String(), func(t *testing.T) {
+ t.Parallel()
+
+ _, err := id.FromHex(algo, strings.Repeat("0", algo.HexLen()-1))
+ if err == nil {
+ t.Fatalf("expected FromHex odd-len error")
+ }
+
+ _, err = id.FromHex(algo, strings.Repeat("0", algo.HexLen()-2))
+ if err == nil {
+ t.Fatalf("expected FromHex wrong-len error")
+ }
+
+ _, err = id.FromHex(algo, "z"+strings.Repeat("0", algo.HexLen()-1))
+ if err == nil {
+ t.Fatalf("expected FromHex invalid-hex error")
+ }
+ })
+ }
+}
+
+func TestFromHexRoundtrip(t *testing.T) {
+ t.Parallel()
+
+ for _, algo := range id.SupportedAlgorithms() {
+ t.Run(algo.String(), func(t *testing.T) {
+ t.Parallel()
+
+ hex := strings.Repeat("01", algo.Size())
+
+ i, err := id.FromHex(algo, hex)
+ if err != nil {
+ t.Fatalf("FromHex failed: %v", err)
+ }
+
+ if got := i.String(); got != hex {
+ t.Fatalf("String() = %q, want %q", got, hex)
+ }
+
+ if got := i.Algorithm().Size(); got != algo.Size() {
+ t.Fatalf("Size() = %d, want %d", got, algo.Size())
+ }
+
+ raw := i.Bytes()
+ if len(raw) != algo.Size() {
+ t.Fatalf("Bytes len = %d, want %d", len(raw), algo.Size())
+ }
+
+ id2, err := id.FromBytes(algo, raw)
+ if err != nil {
+ t.Fatalf("FromBytes failed: %v", err)
+ }
+
+ if id2.String() != hex {
+ t.Fatalf("FromBytes roundtrip = %q, want %q", id2.String(), hex)
+ }
+ })
+ }
+}