Some checks failed
go: build dev binaries / cleanup (push) Successful in 4s
Codespell / Check for spelling errors (push) Failing after 3s
docker: build dev containers / build-rust-binaries (amd64, x86_64-unknown-linux-musl) (push) Failing after 3s
docker: build dev containers / build-dev-containers (push) Has been skipped
docker: build dev containers / build-rust-binaries (arm64, true, aarch64-unknown-linux-musl) (push) Failing after 3s
End to End / FUSE Mount (push) Failing after 2s
EC Integration Tests / EC Integration Tests (push) Failing after 30s
FUSE DLM Integration Tests / FUSE DLM Integration Tests (push) Failing after 3s
FUSE Volume Server Failover Tests / FUSE Volume Server Failover (push) Failing after 3s
FUSE Integration Tests / FUSE Integration Testing (push) Failing after 2s
FUSE P2P Peer Chunk Sharing Integration Tests / FUSE P2P Peer Chunk Sharing (push) Failing after 3s
go: build binary / Go Vet (push) Failing after 2s
go: build binary / Go Vet 32-bit (push) Failing after 3s
go: build binary / Build (push) Failing after 4s
go: build binary / Build cross-platform (freebsd/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/amd64) (push) Failing after 3s
go: build binary / Build cross-platform (darwin/arm64) (push) Failing after 3s
go: build binary / Build cross-platform (windows/arm64) (push) Failing after 3s
go: build binary / Test (push) Failing after 2s
go: build binary / Test 32-bit (push) Failing after 3s
helm: lint and test charts / lint-test (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (11) (push) Failing after 3s
Java Client Integration Tests / Java Integration Tests (17) (push) Failing after 3s
go: build dev binaries / build_dev_linux_windows (amd64, linux) (push) Failing after 2s
go: build dev binaries / build_dev_linux_windows (amd64, windows) (push) Failing after 3s
go: build dev binaries / build_dev_darwin (amd64, darwin) (push) Has been skipped
go: build dev binaries / build_dev_darwin (arm64, darwin) (push) Has been skipped
Java Client Unit Tests / Java Unit Tests (11) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (17) (push) Failing after 2s
Java Client Unit Tests / Java Unit Tests (21) (push) Failing after 3s
Java Client Unit Tests / Java Unit Tests (8) (push) Failing after 3s
Kafka Quick Test (Load Test with Schema Registry) / Kafka Client Load Test (Quick) (push) Failing after 3s
Kafka Gateway Tests / Kafka Unit Tests (unit-tests-1) (push) Failing after 11s
Kafka Gateway Tests / Kafka Integration Tests (Critical) (integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka End-to-End Tests (with SMQ) (e2e-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Consumer Group Tests (Highly Isolated) (consumer-group-1) (push) Failing after 2s
Kafka Gateway Tests / Kafka Client Compatibility (with SMQ) (client-compat-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka SMQ Integration Tests (Full Stack) (smq-integration-1) (push) Failing after 3s
Kafka Gateway Tests / Kafka Protocol Tests (Isolated) (protocol-1) (push) Failing after 3s
KMS Tests / KMS Provider Integration Tests (push) Failing after 2s
KMS Tests / S3 KMS End-to-End Tests (push) Failing after 3s
Master Cold Start Tests / Master Cold Start Tests (push) Failing after 4s
Metadata Subscribe Integration Tests / Metadata Subscribe Integration Tests (push) Failing after 3s
Multi-Master Tests / Multi-Master Failover Tests (push) Failing after 3s
Performance / CPU and Heap Profile (push) Failing after 2s
Performance / S3 Read/Write Benchmark (rust volume) (push) Failing after 3s
pjdfstest POSIX Compliance / pjdfstest (push) Failing after 2s
Plugin Worker Integration Tests / Plugin Worker: erasure_coding (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: vacuum (push) Failing after 3s
Rust Volume Server Tests / Rust Integration Tests (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 1) (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 1) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 2) (push) Failing after 3s
Rust Volume Server Tests / Go Tests with Rust Volume (grpc - Shard 3) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Distributed Tests (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Performance Tests (push) Failing after 3s
Performance / Throughput Benchmark (go volume) (push) Failing after 3s
Performance / Throughput Benchmark (rust volume) (push) Failing after 2s
Performance / S3 Read/Write Benchmark (go volume) (push) Failing after 3s
Plugin Worker Integration Tests / Plugin Worker: volume_balance (push) Failing after 3s
PostgreSQL Gateway Tests / PostgreSQL Basic Tests (push) Failing after 3s
Rust Volume Server Tests / Rust Unit Tests (push) Failing after 2s
Rust Volume Server Tests / Go Tests with Rust Volume (http - Shard 3) (push) Failing after 3s
Rust Plugin Worker Tests / Rust Plugin Worker Build and Unit Tests (push) Failing after 3s
rust: build dev volume server binaries / cleanup (push) Successful in 3s
S3 ETag and ACL Tests / S3 ETag + ACL Integration Tests (push) Failing after 3s
S3 IAM Integration Tests / IAM Unit Tests (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (advanced) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (basic) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (group) (push) Failing after 3s
S3 IAM Integration Tests / S3 IAM Integration Tests (policy-enforcement) (push) Failing after 2s
S3 IAM Integration Tests / S3 IAM Integration Tests (sts) (push) Failing after 4s
S3 Keycloak Integration Tests / S3 Keycloak Integration Tests (push) Failing after 3s
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.11) (push) Failing after 3s
S3 PyArrow Parquet Tests / Go Unit Tests (Implicit Directory) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.12) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-amd64, x86_64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-darwin (darwin-arm64, aarch64-apple-darwin) (push) Has been cancelled
rust: build dev volume server binaries / build-rust-volume-dev-linux (linux-amd64, x86_64-unknown-linux-gnu) (push) Has been cancelled
S3 PyArrow Parquet Tests / PyArrow Parquet Tests (Python 3.9) (push) Has been cancelled
S3 Proxy Signature Tests / S3 Proxy Signature Verification Tests (push) Has been cancelled
S3 SDK V2 Route Disambiguation Tests / S3 SDK V2 Routing Tests (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (quick) (push) Has been cancelled
S3 SSE Tests / S3 SSE Compatibility Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Metadata Persistence Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Copy Operations Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Multipart Upload Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Performance Test (push) Has been cancelled
S3 SSE Tests / S3 Volume Encryption Test (push) Has been cancelled
S3 SSE Tests / S3 SSE Integration Tests (comprehensive) (push) Has been cancelled
Spark Integration Tests / Spark Integration Tests (push) Failing after 2s
Telemetry Integration Tests / telemetry-integration-test (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 1) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 1) (push) Failing after 3s
Ceph S3 tests / Basic S3 tests (KV store) (push) Has been cancelled
Ceph S3 tests / S3 Versioning & Object Lock tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Unit Tests (push) Failing after 3s
Ceph S3 tests / S3 CORS tests (push) Has been cancelled
Ceph S3 tests / SeaweedFS Custom S3 Copy tests (push) Has been cancelled
Ceph S3 tests / Basic S3 tests (SQL store) (push) Has been cancelled
test s3 over https using aws-cli / awscli-tests (push) Has been cancelled
TLS Rotation Integration Tests / TLS Rotation Integration Tests (push) Has been cancelled
Vacuum Integration Tests / Vacuum Integration Tests (push) Has been cancelled
S3 Policy Integration Tests / S3 Policy Variables Integration Tests (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (advanced-policy) (push) Failing after 3s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (basic-policy) (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Enforcement Integration Tests (contextual-policy) (push) Failing after 4s
S3 Policy Integration Tests / Trusted Proxy Detection Tests (push) Failing after 2s
S3 Policy Integration Tests / S3 Policy Shell Integration Tests (push) Failing after 3s
Samba on FUSE Integration / samba-integration (push) Failing after 2s
SFTP Integration Tests / SFTP Integration Testing (push) Failing after 3s
terraform: validate and test modules / fmt, validate, plan-level tests (push) Failing after 3s
terraform: validate and test modules / local cluster smoke test (real weed) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 3) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (grpc - Shard 2) (push) Failing after 3s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 2) (push) Failing after 2s
Volume Server Integration Tests / Volume Server Integration Tests (http - Shard 3) (push) Failing after 5s
mount: windows conformance / WinFsp conformance (push) Has been cancelled
mount: windows / Mount on Windows (push) Has been cancelled
307 lines
9.8 KiB
Go
307 lines
9.8 KiB
Go
package filer_pb
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
// sampleResponse builds a metadata event exercising the fields touched on the
|
|
// hot subscribe path: nested entries, a repeated chunk list, a map, and byte
|
|
// fields.
|
|
func sampleResponse() *SubscribeMetadataResponse {
|
|
entry := func(name string) *Entry {
|
|
return &Entry{
|
|
Name: name,
|
|
IsDirectory: false,
|
|
Chunks: []*FileChunk{
|
|
{
|
|
FileId: "3,01637037d6",
|
|
Offset: 0,
|
|
Size: 1234,
|
|
ModifiedTsNs: 111,
|
|
ETag: "abc",
|
|
Fid: &FileId{VolumeId: 3, FileKey: 0x1637037, Cookie: 0xd6},
|
|
CipherKey: []byte{1, 2, 3, 4},
|
|
},
|
|
},
|
|
Attributes: &FuseAttributes{
|
|
FileSize: 1234, Mtime: 222, FileMode: 0644, Uid: 1000, Gid: 1000,
|
|
GroupName: []string{"staff", "wheel"}, Md5: []byte{9, 8, 7},
|
|
},
|
|
Extended: map[string][]byte{
|
|
"foo": []byte("bar"),
|
|
"baz": []byte("qux"),
|
|
"k3": []byte("v3"),
|
|
},
|
|
Content: []byte("hello"),
|
|
}
|
|
}
|
|
return &SubscribeMetadataResponse{
|
|
Directory: "/buckets/test/dir",
|
|
EventNotification: &EventNotification{
|
|
OldEntry: entry("old.txt"),
|
|
NewEntry: entry("new.txt"),
|
|
DeleteChunks: true,
|
|
NewParentPath: "/buckets/test/dir2",
|
|
IsFromOtherCluster: true,
|
|
Signatures: []int32{101, 202, 303},
|
|
},
|
|
TsNs: 1234567890,
|
|
}
|
|
}
|
|
|
|
// eventWithChunks models a real create/update event: a file split into n chunks,
|
|
// each a nested FileChunk+FileId message. n scales the number of nested messages
|
|
// the decoder must allocate, which is where vtproto's edge over reflection grows.
|
|
func eventWithChunks(n int) *SubscribeMetadataResponse {
|
|
chunks := make([]*FileChunk, n)
|
|
for i := 0; i < n; i++ {
|
|
chunks[i] = &FileChunk{
|
|
FileId: fmt.Sprintf("%d,%08x%04x", i%64, i*7919, i%251),
|
|
Offset: int64(i) * 8 << 20,
|
|
Size: 8 << 20,
|
|
ModifiedTsNs: 1700000000000000000 + int64(i),
|
|
ETag: fmt.Sprintf("etag-%d", i),
|
|
Fid: &FileId{VolumeId: uint32(i%64 + 1), FileKey: uint64(i * 7919), Cookie: uint32(i % 251)},
|
|
}
|
|
}
|
|
return &SubscribeMetadataResponse{
|
|
Directory: "/buckets/data/2026/07/15",
|
|
EventNotification: &EventNotification{
|
|
NewEntry: &Entry{
|
|
Name: "object.bin",
|
|
Chunks: chunks,
|
|
Attributes: &FuseAttributes{FileSize: uint64(n) * 8 << 20, Mtime: 1700000000, FileMode: 0644, Uid: 1000, Gid: 1000},
|
|
},
|
|
Signatures: []int32{12345},
|
|
},
|
|
TsNs: 1700000000000000000,
|
|
}
|
|
}
|
|
|
|
// TestVTWireCompatibility guards that the vtproto-generated MarshalVT/UnmarshalVT
|
|
// stay wire-compatible with the reflection-based proto path in both directions,
|
|
// so adopting VT on the metadata hot paths cannot silently corrupt events.
|
|
func TestVTWireCompatibility(t *testing.T) {
|
|
orig := sampleResponse()
|
|
|
|
// vt marshal -> proto unmarshal
|
|
vtBytes, err := orig.MarshalVT()
|
|
if err != nil {
|
|
t.Fatalf("MarshalVT: %v", err)
|
|
}
|
|
var fromVT SubscribeMetadataResponse
|
|
if err := proto.Unmarshal(vtBytes, &fromVT); err != nil {
|
|
t.Fatalf("proto.Unmarshal(vtBytes): %v", err)
|
|
}
|
|
if !proto.Equal(orig, &fromVT) {
|
|
t.Fatalf("proto.Unmarshal(MarshalVT) diverged from original")
|
|
}
|
|
|
|
// proto marshal -> vt unmarshal
|
|
protoBytes, err := proto.Marshal(orig)
|
|
if err != nil {
|
|
t.Fatalf("proto.Marshal: %v", err)
|
|
}
|
|
var fromProto SubscribeMetadataResponse
|
|
if err := fromProto.UnmarshalVT(protoBytes); err != nil {
|
|
t.Fatalf("UnmarshalVT(protoBytes): %v", err)
|
|
}
|
|
if !proto.Equal(orig, &fromProto) {
|
|
t.Fatalf("UnmarshalVT(proto.Marshal) diverged from original")
|
|
}
|
|
|
|
// MarshalToSizedBufferVT into a pre-sized slice matches MarshalVT, the write
|
|
// path used by the log buffer.
|
|
sized := make([]byte, orig.SizeVT())
|
|
if _, err := orig.MarshalToSizedBufferVT(sized); err != nil {
|
|
t.Fatalf("MarshalToSizedBufferVT: %v", err)
|
|
}
|
|
var fromSized SubscribeMetadataResponse
|
|
if err := fromSized.UnmarshalVT(sized); err != nil {
|
|
t.Fatalf("UnmarshalVT(sized): %v", err)
|
|
}
|
|
if !proto.Equal(orig, &fromSized) {
|
|
t.Fatalf("MarshalToSizedBufferVT diverged from original")
|
|
}
|
|
|
|
// LogEntry carrying a marshaled event, mirroring the log buffer write path.
|
|
le := &LogEntry{TsNs: 7, PartitionKeyHash: 9, Data: vtBytes, Key: []byte("k"), Offset: 42}
|
|
leBytes, err := le.MarshalVT()
|
|
if err != nil {
|
|
t.Fatalf("LogEntry.MarshalVT: %v", err)
|
|
}
|
|
var leDecoded LogEntry
|
|
if err := proto.Unmarshal(leBytes, &leDecoded); err != nil {
|
|
t.Fatalf("proto.Unmarshal(LogEntry): %v", err)
|
|
}
|
|
if !proto.Equal(le, &leDecoded) {
|
|
t.Fatalf("LogEntry vt/proto roundtrip diverged")
|
|
}
|
|
}
|
|
|
|
// TestUTF8Validation documents the deliberate UTF-8 difference between the two
|
|
// decoders. UnmarshalVT skips proto3's UTF-8 validation for string fields, so
|
|
// the metadata delivery paths keep decoding SubscribeMetadataResponse with
|
|
// proto.Unmarshal; only LogEntry (bytes-only) decodes use UnmarshalVT.
|
|
func TestUTF8Validation(t *testing.T) {
|
|
// SubscribeMetadataResponse{Directory: "\xff"}: field 1 (string), wire type 2,
|
|
// length 1, byte 0xff.
|
|
malformed := []byte{0x0a, 0x01, 0xff}
|
|
|
|
var viaProto SubscribeMetadataResponse
|
|
if err := proto.Unmarshal(malformed, &viaProto); err == nil {
|
|
t.Fatal("proto.Unmarshal accepted invalid UTF-8 in a string field; expected rejection")
|
|
}
|
|
|
|
var viaVT SubscribeMetadataResponse
|
|
if err := viaVT.UnmarshalVT(malformed); err != nil {
|
|
t.Fatalf("UnmarshalVT rejected invalid UTF-8: %v", err)
|
|
}
|
|
if viaVT.Directory != "\xff" {
|
|
t.Fatalf("UnmarshalVT Directory = %q, want \\xff", viaVT.Directory)
|
|
}
|
|
|
|
// LogEntry carries only bytes fields, so the decoders agree on arbitrary bytes;
|
|
// that is why the log entry decode paths can use UnmarshalVT.
|
|
// LogEntry{Data: "\xff"}: field 3 (bytes), wire type 2, length 1, byte 0xff.
|
|
leBytes := []byte{0x1a, 0x01, 0xff}
|
|
var leProto LogEntry
|
|
if err := proto.Unmarshal(leBytes, &leProto); err != nil {
|
|
t.Fatalf("proto.Unmarshal LogEntry: %v", err)
|
|
}
|
|
var leVT LogEntry
|
|
if err := leVT.UnmarshalVT(leBytes); err != nil {
|
|
t.Fatalf("UnmarshalVT LogEntry: %v", err)
|
|
}
|
|
if !proto.Equal(&leProto, &leVT) {
|
|
t.Fatal("LogEntry proto/VT decode of a bytes field diverged")
|
|
}
|
|
}
|
|
|
|
var chunkCounts = []int{1, 8, 32, 128}
|
|
|
|
// BenchmarkUnmarshal is the decode hot path: each subscriber decodes every
|
|
// delivered event, so this cost is paid once per (event, subscriber).
|
|
func BenchmarkUnmarshal(b *testing.B) {
|
|
for _, n := range chunkCounts {
|
|
data, _ := proto.Marshal(eventWithChunks(n))
|
|
b.Run(fmt.Sprintf("proto/chunks=%d", n), func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
var m SubscribeMetadataResponse
|
|
if err := proto.Unmarshal(data, &m); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
b.Run(fmt.Sprintf("vt/chunks=%d", n), func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
var m SubscribeMetadataResponse
|
|
if err := m.UnmarshalVT(data); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkMarshal is the encode path: each metadata write marshals one LogEntry
|
|
// payload.
|
|
func BenchmarkMarshal(b *testing.B) {
|
|
for _, n := range chunkCounts {
|
|
ev := eventWithChunks(n)
|
|
b.Run(fmt.Sprintf("proto/chunks=%d", n), func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
if _, err := proto.Marshal(ev); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
b.Run(fmt.Sprintf("vt/chunks=%d", n), func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
if _, err := ev.MarshalVT(); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkMarshalIntoBuffer mirrors the log buffer write path: marshal into a
|
|
// reused destination buffer. proto.Marshal must allocate a fresh slice and copy;
|
|
// SizeVT + MarshalToSizedBufferVT writes straight into the destination.
|
|
func BenchmarkMarshalIntoBuffer(b *testing.B) {
|
|
for _, n := range chunkCounts {
|
|
ev := eventWithChunks(n)
|
|
dst := make([]byte, 0, ev.SizeVT()*2)
|
|
b.Run(fmt.Sprintf("proto+copy/chunks=%d", n), func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
data, err := proto.Marshal(ev)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
dst = dst[:len(data)]
|
|
copy(dst, data)
|
|
}
|
|
})
|
|
b.Run(fmt.Sprintf("vt-sized/chunks=%d", n), func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
size := ev.SizeVT()
|
|
dst = dst[:size]
|
|
if _, err := ev.MarshalToSizedBufferVT(dst); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// The log position fields must survive VT round-trips, or a VT-marshaled
|
|
// response silently loses the version the mount fences handles with.
|
|
func TestVtProtoPreservesLogTsNs(t *testing.T) {
|
|
messages := []interface {
|
|
MarshalVT() ([]byte, error)
|
|
}{
|
|
&LookupDirectoryEntryResponse{LogTsNs: 42},
|
|
&CacheRemoteObjectToLocalClusterResponse{LogTsNs: 43},
|
|
&CreateEntryResponse{LogTsNs: 44},
|
|
&UpdateEntryResponse{LogTsNs: 45},
|
|
}
|
|
for i, m := range messages {
|
|
data, err := m.MarshalVT()
|
|
if err != nil {
|
|
t.Fatalf("MarshalVT %d: %v", i, err)
|
|
}
|
|
switch v := m.(type) {
|
|
case *LookupDirectoryEntryResponse:
|
|
out := &LookupDirectoryEntryResponse{}
|
|
if err := out.UnmarshalVT(data); err != nil || out.LogTsNs != v.LogTsNs {
|
|
t.Fatalf("LookupDirectoryEntryResponse round-trip LogTsNs = %d, %v; want %d", out.LogTsNs, err, v.LogTsNs)
|
|
}
|
|
case *CacheRemoteObjectToLocalClusterResponse:
|
|
out := &CacheRemoteObjectToLocalClusterResponse{}
|
|
if err := out.UnmarshalVT(data); err != nil || out.LogTsNs != v.LogTsNs {
|
|
t.Fatalf("CacheRemoteObjectToLocalClusterResponse round-trip LogTsNs = %d, %v; want %d", out.LogTsNs, err, v.LogTsNs)
|
|
}
|
|
case *CreateEntryResponse:
|
|
out := &CreateEntryResponse{}
|
|
if err := out.UnmarshalVT(data); err != nil || out.LogTsNs != v.LogTsNs {
|
|
t.Fatalf("CreateEntryResponse round-trip LogTsNs = %d, %v; want %d", out.LogTsNs, err, v.LogTsNs)
|
|
}
|
|
case *UpdateEntryResponse:
|
|
out := &UpdateEntryResponse{}
|
|
if err := out.UnmarshalVT(data); err != nil || out.LogTsNs != v.LogTsNs {
|
|
t.Fatalf("UpdateEntryResponse round-trip LogTsNs = %d, %v; want %d", out.LogTsNs, err, v.LogTsNs)
|
|
}
|
|
}
|
|
}
|
|
}
|