mirror of
https://github.com/ipfs/kubo.git
synced 2025-10-18 20:24:30 +08:00

To avoid duplicating fields and making the code easier to follow. Remove all of `FSNode` previous fields in favor on a single `pb.Data` structure that is not exported. Accessor methods are added only for the necessary internal fields. This takes up more memory, `pb.Data` is always created inside `FSNode` and it stays there instead of just being created and destroyed during the (un)marshal operations. The removed fields `Data`, `blocksizes` and `Type` had a direct counterpart in the embedded `pb.Data` structure, in contrast (only) the `subtotal` field doesn't have one, it was used as a temporary accumulator to track the `Filesize`, which is now being kept updated on every modification (to ensure the entire `FSNode` is always at a valid state), so `subtotal` could just be removed without the addition of any other field (this temporary accumulator was obscuring how `Filesize` was computed). To keep `Filesize` up to date a method was added (`UpdateFilesize()`) to adjust its value in the two places where the file size could be modified, when changing its data (in `SetData()`, accessor method added) and when adding or removing child nodes (in `AddBlockSize()` and `RemoveBlockSize()`). A constructor method was added (`NewFSNode()`) to initialize the required fields, like `Type` which is explicitly set, this deprecates the previous methodology of just calling `new(FSNode)` and relying in the default value of `pb.Data_DataType` (`Data_Raw`) to avoid an explicit assignment. Also, `Filesize` is initialized to avoid being left with a `nil` value before marshaling empty nodes, which would result in a different hash from previous versions, to be backwards compatible. Previous versions of `GetBytes()` always set the `Filesize` value, even though it is reflected as an `optional` field in the `.proto` file (this may be an inaccurate field rule). Without the duplicated fields the functions `GetBytes()` and `FSNodeFromBytes()` are now reduced to simple `Marshal()` and `Unmarshal()` operations respectively. License: MIT Signed-off-by: Lucas Molas <schomatis@gmail.com>
161 lines
2.9 KiB
Go
161 lines
2.9 KiB
Go
package unixfs
|
|
|
|
import (
|
|
"bytes"
|
|
"testing"
|
|
|
|
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
|
|
|
|
pb "github.com/ipfs/go-ipfs/unixfs/pb"
|
|
)
|
|
|
|
func TestFSNode(t *testing.T) {
|
|
fsn := NewFSNode(TFile)
|
|
for i := 0; i < 16; i++ {
|
|
fsn.AddBlockSize(100)
|
|
}
|
|
fsn.RemoveBlockSize(15)
|
|
|
|
fsn.SetData(make([]byte, 128))
|
|
|
|
b, err := fsn.GetBytes()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
pbn := new(pb.Data)
|
|
err = proto.Unmarshal(b, pbn)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ds, err := DataSize(b)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
nKids := fsn.NumChildren()
|
|
if nKids != 15 {
|
|
t.Fatal("Wrong number of child nodes")
|
|
}
|
|
|
|
if ds != (100*15)+128 {
|
|
t.Fatal("Datasize calculations incorrect!")
|
|
}
|
|
|
|
nfsn, err := FSNodeFromBytes(b)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if nfsn.FileSize() != (100*15)+128 {
|
|
t.Fatal("fsNode FileSize calculations incorrect")
|
|
}
|
|
}
|
|
|
|
func TestPBdataTools(t *testing.T) {
|
|
raw := []byte{0x00, 0x01, 0x02, 0x17, 0xA1}
|
|
rawPB := WrapData(raw)
|
|
|
|
pbDataSize, err := DataSize(rawPB)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
same := len(raw) == int(pbDataSize)
|
|
if !same {
|
|
t.Fatal("WrapData changes the size of data.")
|
|
}
|
|
|
|
rawPBBytes, err := UnwrapData(rawPB)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
same = bytes.Equal(raw, rawPBBytes)
|
|
if !same {
|
|
t.Fatal("Unwrap failed to produce the correct wrapped data.")
|
|
}
|
|
|
|
rawPBdata, err := FromBytes(rawPB)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
isRaw := rawPBdata.GetType() == TRaw
|
|
if !isRaw {
|
|
t.Fatal("WrapData does not create pb.Data_Raw!")
|
|
}
|
|
|
|
catFile := []byte("Mr_Meowgie.gif")
|
|
catPBfile := FilePBData(catFile, 17)
|
|
catSize, err := DataSize(catPBfile)
|
|
if catSize != 17 {
|
|
t.Fatal("FilePBData is the wrong size.")
|
|
}
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
dirPB := FolderPBData()
|
|
dir, err := FromBytes(dirPB)
|
|
isDir := dir.GetType() == TDirectory
|
|
if !isDir {
|
|
t.Fatal("FolderPBData does not create a directory!")
|
|
}
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, dirErr := DataSize(dirPB)
|
|
if dirErr == nil {
|
|
t.Fatal("DataSize didn't throw an error when taking the size of a directory.")
|
|
}
|
|
|
|
catSym, err := SymlinkData("/ipfs/adad123123/meowgie.gif")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
catSymPB, err := FromBytes(catSym)
|
|
isSym := catSymPB.GetType() == TSymlink
|
|
if !isSym {
|
|
t.Fatal("Failed to make a Symlink.")
|
|
}
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, sizeErr := DataSize(catSym)
|
|
if sizeErr == nil {
|
|
t.Fatal("DataSize didn't throw an error when taking the size of a Symlink.")
|
|
}
|
|
|
|
}
|
|
|
|
func TestMetadata(t *testing.T) {
|
|
meta := &Metadata{
|
|
MimeType: "audio/aiff",
|
|
Size: 12345,
|
|
}
|
|
|
|
_, err := meta.Bytes()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
metaPB, err := BytesForMetadata(meta)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
meta, err = MetadataFromBytes(metaPB)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
mimeAiff := meta.MimeType == "audio/aiff"
|
|
if !mimeAiff {
|
|
t.Fatal("Metadata does not Marshal and Unmarshal properly!")
|
|
}
|
|
|
|
}
|