| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- package needle
- import (
- "bytes"
- "os"
- "testing"
- "time"
- "github.com/seaweedfs/seaweedfs/weed/storage/backend"
- "github.com/seaweedfs/seaweedfs/weed/storage/types"
- )
- func TestAppend(t *testing.T) {
- n := &Needle{
- Cookie: types.Cookie(123), // Cookie Cookie `comment:"random number to mitigate brute force lookups"`
- Id: types.NeedleId(123), // Id NeedleId `comment:"needle id"`
- Size: 8, // Size uint32 `comment:"sum of DataSize,Data,NameSize,Name,MimeSize,Mime"`
- DataSize: 4, // DataSize uint32 `comment:"Data size"` //version2
- Data: []byte("abcd"), // Data []byte `comment:"The actual file data"`
- Flags: 0, // Flags byte `comment:"boolean flags"` //version2
- NameSize: 0, // NameSize uint8 //version2
- Name: nil, // Name []byte `comment:"maximum 256 characters"` //version2
- MimeSize: 0, // MimeSize uint8 //version2
- Mime: nil, // Mime []byte `comment:"maximum 256 characters"` //version2
- PairsSize: 0, // PairsSize uint16 //version2
- Pairs: nil, // Pairs []byte `comment:"additional name value pairs, json format, maximum 6
- LastModified: 123, // LastModified uint64 //only store LastModifiedBytesLength bytes, which is 5 bytes
- Ttl: nil, // Ttl *TTL
- Checksum: 123, // Checksum CRC `comment:"CRC32 to check integrity"`
- AppendAtNs: 123, // AppendAtNs uint64 `comment:"append timestamp in nano seconds"` //version3
- Padding: nil, // Padding []byte `comment:"Aligned to 8 bytes"`
- }
- tempFile, err := os.CreateTemp("", ".dat")
- if err != nil {
- t.Errorf("Fail TempFile. %v", err)
- return
- }
- /*
- uint8 : 0 to 255
- uint16 : 0 to 65535
- uint32 : 0 to 4294967295
- uint64 : 0 to 18446744073709551615
- int8 : -128 to 127
- int16 : -32768 to 32767
- int32 : -2147483648 to 2147483647
- int64 : -9223372036854775808 to 9223372036854775807
- */
- fileSize := int64(4294967296) + 10000
- tempFile.Truncate(fileSize)
- defer func() {
- tempFile.Close()
- os.Remove(tempFile.Name())
- }()
- datBackend := backend.NewDiskFile(tempFile)
- defer datBackend.Close()
- offset, _, _, _ := n.Append(datBackend, GetCurrentVersion())
- if offset != uint64(fileSize) {
- t.Errorf("Fail to Append Needle.")
- }
- }
- func versionString(v Version) string {
- switch v {
- case Version1:
- return "Version1"
- case Version2:
- return "Version2"
- case Version3:
- return "Version3"
- default:
- return "UnknownVersion"
- }
- }
- func TestWriteNeedle_CompatibilityWithLegacy(t *testing.T) {
- versions := []Version{Version1, Version2, Version3}
- for _, version := range versions {
- t.Run(versionString(version), func(t *testing.T) {
- n := &Needle{
- Cookie: 0x12345678,
- Id: 0x1122334455667788,
- Data: []byte("hello world"),
- Flags: 0xFF,
- Name: []byte("filename.txt"),
- Mime: []byte("text/plain"),
- LastModified: 0x1234567890,
- Ttl: nil, // Add TTL if needed
- Pairs: []byte("key=value"),
- PairsSize: 9,
- Checksum: 0xCAFEBABE,
- AppendAtNs: 0xDEADBEEF,
- }
- // Legacy
- legacyBuf := &bytes.Buffer{}
- _, _, err := n.LegacyPrepareWriteBuffer(version, legacyBuf)
- if err != nil {
- t.Fatalf("LegacyPrepareWriteBuffer failed: %v", err)
- }
- // New
- newBuf := &bytes.Buffer{}
- offset := uint64(0)
- switch version {
- case Version1:
- _, _, err = writeNeedleV1(n, offset, newBuf)
- case Version2:
- _, _, err = writeNeedleV2(n, offset, newBuf)
- case Version3:
- _, _, err = writeNeedleV3(n, offset, newBuf)
- }
- if err != nil {
- t.Fatalf("writeNeedleV%d failed: %v", version, err)
- }
- if !bytes.Equal(legacyBuf.Bytes(), newBuf.Bytes()) {
- t.Errorf("Data layout mismatch for version %d\nLegacy: %x\nNew: %x", version, legacyBuf.Bytes(), newBuf.Bytes())
- }
- })
- }
- }
- type mockBackendWriter struct {
- buf *bytes.Buffer
- }
- func (m *mockBackendWriter) WriteAt(p []byte, off int64) (n int, err error) {
- return m.buf.Write(p)
- }
- func (m *mockBackendWriter) GetStat() (int64, time.Time, error) {
- return 0, time.Time{}, nil
- }
- func (m *mockBackendWriter) Truncate(size int64) error {
- return nil
- }
- func (m *mockBackendWriter) Name() string {
- return "mock"
- }
- func (m *mockBackendWriter) Close() error {
- return nil
- }
- func (m *mockBackendWriter) Sync() error {
- return nil
- }
- func (m *mockBackendWriter) ReadAt(p []byte, off int64) (n int, err error) {
- // Not used in this test
- return 0, nil
- }
|