package bits import ( "fmt" "testing" "github.com/lyoshenka/bencode" ) func TestBitmap(t *testing.T) { a := Bitmap{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, } b := Bitmap{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 46, } c := Bitmap{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, } if !a.Equals(a) { t.Error("bitmap does not equal itself") } if a.Equals(b) { t.Error("bitmap equals another bitmap with different id") } if !a.Xor(b).Equals(c) { t.Error(a.Xor(b)) } if c.PrefixLen() != 375 { t.Error(c.PrefixLen()) } if b.Cmp(a) < 0 { t.Error("bitmap fails Cmp test") } if a.Closer(c, b) || !a.Closer(b, c) || c.Closer(a, b) || c.Closer(b, c) { t.Error("bitmap fails Closer test") } id := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" if FromHexP(id).Hex() != id { t.Error(FromHexP(id).Hex()) } } func TestBitmap_GetBit(t *testing.T) { tt := []struct { bit int expected bool panic bool }{ {bit: 383, expected: false, panic: false}, {bit: 382, expected: true, panic: false}, {bit: 381, expected: false, panic: false}, {bit: 380, expected: true, panic: false}, } b := FromShortHexP("a") for _, test := range tt { actual := getBit(b[:], test.bit) if test.expected != actual { t.Errorf("getting bit %d of %s: expected %t, got %t", test.bit, b.HexSimplified(), test.expected, actual) } } } func TestBitmap_SetBit(t *testing.T) { tt := []struct { hex string bit int one bool expected string panic bool }{ {hex: "0", bit: 383, one: true, expected: "1", panic: false}, {hex: "0", bit: 382, one: true, expected: "2", panic: false}, {hex: "0", bit: 381, one: true, expected: "4", panic: false}, {hex: "0", bit: 385, one: true, expected: "1", panic: true}, {hex: "0", bit: 384, one: true, expected: "1", panic: true}, } for _, test := range tt { expected := FromShortHexP(test.expected) actual := FromShortHexP(test.hex) if test.panic { assertPanic(t, fmt.Sprintf("setting bit %d to %t", test.bit, test.one), func() { setBit(actual[:], test.bit, test.one) }) } else { setBit(actual[:], test.bit, test.one) if !expected.Equals(actual) { t.Errorf("setting bit %d to %t: expected %s, got %s", test.bit, test.one, test.expected, actual.HexSimplified()) } } } } func TestBitmap_FromHexShort(t *testing.T) { tt := []struct { short string long string }{ {short: "", long: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {short: "0", long: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {short: "00000", long: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {short: "9473745bc", long: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000009473745bc"}, {short: "09473745bc", long: "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000009473745bc"}, {short: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", long: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}, } for _, test := range tt { short := FromShortHexP(test.short) long := FromHexP(test.long) if !short.Equals(long) { t.Errorf("short hex %s: expected %s, got %s", test.short, long.Hex(), short.Hex()) } } } func TestBitmapMarshal(t *testing.T) { b := FromStringP("123456789012345678901234567890123456789012345678") encoded, err := bencode.EncodeBytes(b) if err != nil { t.Error(err) } if string(encoded) != "48:123456789012345678901234567890123456789012345678" { t.Error("encoding does not match expected") } } func TestBitmapMarshalEmbedded(t *testing.T) { e := struct { A string B Bitmap C int }{ A: "1", B: FromStringP("222222222222222222222222222222222222222222222222"), C: 3, } encoded, err := bencode.EncodeBytes(e) if err != nil { t.Error(err) } if string(encoded) != "d1:A1:11:B48:2222222222222222222222222222222222222222222222221:Ci3ee" { t.Error("encoding does not match expected") } } func TestBitmapMarshalEmbedded2(t *testing.T) { encoded, err := bencode.EncodeBytes([]interface{}{ FromStringP("333333333333333333333333333333333333333333333333"), }) if err != nil { t.Error(err) } if string(encoded) != "l48:333333333333333333333333333333333333333333333333e" { t.Error("encoding does not match expected") } } func TestBitmap_PrefixLen(t *testing.T) { tt := []struct { hex string len int }{ {len: 0, hex: "F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {len: 0, hex: "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {len: 1, hex: "700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {len: 1, hex: "400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {len: 384, hex: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {len: 383, hex: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"}, {len: 382, hex: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"}, {len: 382, hex: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"}, } for _, test := range tt { len := FromHexP(test.hex).PrefixLen() if len != test.len { t.Errorf("got prefix len %d; expected %d for %s", len, test.len, test.hex) } } } func TestBitmap_Prefix(t *testing.T) { allOne := FromHexP("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") zerosTT := []struct { zeros int expected string }{ {zeros: -123, expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {zeros: 0, expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {zeros: 1, expected: "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {zeros: 69, expected: "000000000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {zeros: 383, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"}, {zeros: 384, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {zeros: 400, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, } for _, test := range zerosTT { expected := FromHexP(test.expected) actual := allOne.Prefix(test.zeros, false) if !actual.Equals(expected) { t.Errorf("%d zeros: got %s; expected %s", test.zeros, actual.Hex(), expected.Hex()) } } for i := 0; i < NumBits; i++ { b := allOne.Prefix(i, false) if b.PrefixLen() != i { t.Errorf("got prefix len %d; expected %d for %s", b.PrefixLen(), i, b.Hex()) } } allZero := FromHexP("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") onesTT := []struct { ones int expected string }{ {ones: -123, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {ones: 0, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {ones: 1, expected: "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {ones: 69, expected: "fffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {ones: 383, expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, {ones: 384, expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {ones: 400, expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, } for _, test := range onesTT { expected := FromHexP(test.expected) actual := allZero.Prefix(test.ones, true) if !actual.Equals(expected) { t.Errorf("%d ones: got %s; expected %s", test.ones, actual.Hex(), expected.Hex()) } } } func TestBitmap_Suffix(t *testing.T) { allOne := FromHexP("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") zerosTT := []struct { zeros int expected string }{ {zeros: -123, expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {zeros: 0, expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {zeros: 1, expected: "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, {zeros: 69, expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000000000000"}, {zeros: 383, expected: "800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {zeros: 384, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {zeros: 400, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, } for _, test := range zerosTT { expected := FromHexP(test.expected) actual := allOne.Suffix(test.zeros, false) if !actual.Equals(expected) { t.Errorf("%d zeros: got %s; expected %s", test.zeros, actual.Hex(), expected.Hex()) } } for i := 0; i < NumBits; i++ { b := allOne.Prefix(i, false) if b.PrefixLen() != i { t.Errorf("got prefix len %d; expected %d for %s", b.PrefixLen(), i, b.Hex()) } } allZero := FromHexP("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") onesTT := []struct { ones int expected string }{ {ones: -123, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {ones: 0, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, {ones: 1, expected: "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"}, {ones: 69, expected: "0000000000000000000000000000000000000000000000000000000000000000000000000000001fffffffffffffffff"}, {ones: 383, expected: "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {ones: 384, expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, {ones: 400, expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, } for _, test := range onesTT { expected := FromHexP(test.expected) actual := allZero.Suffix(test.ones, true) if !actual.Equals(expected) { t.Errorf("%d ones: got %s; expected %s", test.ones, actual.Hex(), expected.Hex()) } } } func TestBitmap_Add(t *testing.T) { tt := []struct { a, b, sum string panic bool }{ {"0", "0", "0", false}, {"0", "1", "1", false}, {"1", "0", "1", false}, {"1", "1", "2", false}, {"8", "4", "c", false}, {"1000", "0010", "1010", false}, {"1111", "1111", "2222", false}, {"ffff", "1", "10000", false}, {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", false}, {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "1", "", true}, } for _, test := range tt { a := FromShortHexP(test.a) b := FromShortHexP(test.b) expected := FromShortHexP(test.sum) if test.panic { assertPanic(t, fmt.Sprintf("adding %s and %s", test.a, test.b), func() { a.Add(b) }) } else { actual := a.Add(b) if !expected.Equals(actual) { t.Errorf("adding %s and %s; expected %s, got %s", test.a, test.b, test.sum, actual.HexSimplified()) } } } } func TestBitmap_Sub(t *testing.T) { tt := []struct { a, b, sum string panic bool }{ {"0", "0", "0", false}, {"1", "0", "1", false}, {"1", "1", "0", false}, {"8", "4", "4", false}, {"f", "9", "6", false}, {"f", "e", "1", false}, {"10", "f", "1", false}, {"2222", "1111", "1111", false}, {"ffff", "1", "fffe", false}, {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", false}, {"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0", false}, {"0", "1", "", true}, } for _, test := range tt { a := FromShortHexP(test.a) b := FromShortHexP(test.b) expected := FromShortHexP(test.sum) if test.panic { assertPanic(t, fmt.Sprintf("subtracting %s - %s", test.a, test.b), func() { a.Sub(b) }) } else { actual := a.Sub(b) if !expected.Equals(actual) { t.Errorf("subtracting %s - %s; expected %s, got %s", test.a, test.b, test.sum, actual.HexSimplified()) } } } } func assertPanic(t *testing.T, text string, f func()) { defer func() { if r := recover(); r == nil { t.Errorf("%s: did not panic as expected", text) } }() f() }