func TestMetaScanBounds(t *testing.T) { defer leaktest.AfterTest(t) testCases := []struct { key, expStart, expEnd proto.Key }{ { key: proto.Key{}, expStart: Meta1Prefix, expEnd: Meta1Prefix.PrefixEnd(), }, { key: proto.Key("foo"), expStart: proto.Key("foo").Next(), expEnd: proto.Key("foo")[:len(Meta1Prefix)].PrefixEnd(), }, { key: proto.MakeKey(Meta1Prefix, proto.KeyMax), expStart: proto.MakeKey(Meta1Prefix, proto.KeyMax), expEnd: Meta1Prefix.PrefixEnd(), }, } for i, test := range testCases { resStart, resEnd := MetaScanBounds(test.key) if !resStart.Equal(test.expStart) || !resEnd.Equal(test.expEnd) { t.Errorf("%d: range bounds %q-%q don't match expected bounds %q-%q for key %q", i, resStart, resEnd, test.expStart, test.expEnd, test.key) } } }
func TestMetaReverseScanBounds(t *testing.T) { defer leaktest.AfterTest(t) testCases := []struct { key, expStart, expEnd proto.Key err error }{ { key: proto.Key{}, expStart: nil, expEnd: nil, err: NewInvalidRangeMetaKeyError("KeyMin or Meta1Prefix can't be used as the key of reverse scan", proto.Key{}), }, { key: Meta1Prefix, expStart: nil, expEnd: nil, err: NewInvalidRangeMetaKeyError("KeyMin or Meta1Prefix can't be used as the key of reverse scan", Meta1Prefix), }, { key: proto.MakeKey(Meta2Prefix, proto.Key("foo")), expStart: Meta2Prefix, expEnd: proto.MakeKey(Meta2Prefix, proto.Key("foo\x00")), err: nil, }, { key: proto.MakeKey(Meta1Prefix, proto.Key("foo")), expStart: Meta1Prefix, expEnd: proto.MakeKey(Meta1Prefix, proto.Key("foo\x00")), err: nil, }, { key: Meta2Prefix, expStart: Meta1Prefix, expEnd: Meta2Prefix.Next(), err: nil, }, } for i, test := range testCases { resStart, resEnd, _ := MetaReverseScanBounds(test.key) if !resStart.Equal(test.expStart) || !resEnd.Equal(test.expEnd) { t.Errorf("%d: range bounds %q-%q don't match expected bounds %q-%q for key %q", i, resStart, resEnd, test.expStart, test.expEnd, test.key) } } }
// TestBootstrapCluster verifies the results of bootstrapping a // cluster. Uses an in memory engine. func TestBootstrapCluster(t *testing.T) { defer leaktest.AfterTest(t) stopper := stop.NewStopper() e := engine.NewInMem(proto.Attributes{}, 1<<20) localDB, err := BootstrapCluster("cluster-1", []engine.Engine{e}, stopper) if err != nil { t.Fatal(err) } defer stopper.Stop() // Scan the complete contents of the local database. rows, err := localDB.Scan(keys.LocalPrefix.PrefixEnd(), proto.KeyMax, 0) if err != nil { t.Fatal(err) } var keys []proto.Key for _, kv := range rows { keys = append(keys, kv.Key) } // TODO(marc): this depends on the sql system objects. var expectedKeys = []proto.Key{ proto.MakeKey(proto.Key("\x00\x00meta1"), proto.KeyMax), proto.MakeKey(proto.Key("\x00\x00meta2"), proto.KeyMax), proto.Key("\x00desc-idgen"), proto.Key("\x00node-idgen"), proto.Key("\x00range-tree-root"), proto.Key("\x00store-idgen"), proto.Key("\x00zone"), proto.Key("\xff\n\x02\n\x01\tsystem\x00\x01\n\x03"), proto.Key("\xff\n\x02\n\x01\n\x01descriptor\x00\x01\n\x03"), proto.Key("\xff\n\x02\n\x01\n\x01namespace\x00\x01\n\x03"), proto.Key("\xff\n\x02\n\x01\n\x01users\x00\x01\n\x03"), proto.Key("\xff\n\x03\n\x01\n\x01\n\x02"), proto.Key("\xff\n\x03\n\x01\n\x02\n\x02"), proto.Key("\xff\n\x03\n\x01\n\x03\n\x02"), proto.Key("\xff\n\x03\n\x01\n\x04\n\x02"), } if !reflect.DeepEqual(keys, expectedKeys) { t.Errorf("expected keys mismatch:\n%s\n -- vs. -- \n\n%s", formatKeys(keys), formatKeys(expectedKeys)) } // TODO(spencer): check values. }
// TestBootstrapCluster verifies the results of bootstrapping a // cluster. Uses an in memory engine. func TestBootstrapCluster(t *testing.T) { defer leaktest.AfterTest(t) stopper := stop.NewStopper() e := engine.NewInMem(proto.Attributes{}, 1<<20) localDB, err := BootstrapCluster("cluster-1", []engine.Engine{e}, stopper) if err != nil { t.Fatal(err) } defer stopper.Stop() // Scan the complete contents of the local database. rows, err := localDB.Scan(keys.LocalPrefix.PrefixEnd(), proto.KeyMax, 0) if err != nil { t.Fatal(err) } var foundKeys proto.KeySlice for _, kv := range rows { foundKeys = append(foundKeys, kv.Key) } var expectedKeys = proto.KeySlice{ proto.MakeKey(proto.Key("\x00\x00meta1"), proto.KeyMax), proto.MakeKey(proto.Key("\x00\x00meta2"), proto.KeyMax), proto.Key("\x00node-idgen"), proto.Key("\x00range-tree-root"), proto.Key("\x00store-idgen"), proto.Key("\x00zone"), } // Add the initial keys for sql. for _, kv := range sql.GetInitialSystemValues() { expectedKeys = append(expectedKeys, kv.Key) } // Resort the list. The sql values are not sorted. sort.Sort(expectedKeys) if !reflect.DeepEqual(foundKeys, expectedKeys) { t.Errorf("expected keys mismatch:\n%s\n -- vs. -- \n\n%s", formatKeys(foundKeys), formatKeys(expectedKeys)) } // TODO(spencer): check values. }
func TestValidateRangeMetaKey(t *testing.T) { defer leaktest.AfterTest(t) testCases := []struct { key proto.Key expErr bool }{ {proto.KeyMin, false}, {proto.Key("\x00"), true}, {Meta1Prefix[:len(Meta1Prefix)-1], true}, {Meta1Prefix, false}, {proto.MakeKey(Meta1Prefix, proto.KeyMax), false}, {proto.MakeKey(Meta2Prefix, proto.KeyMax), true}, {proto.MakeKey(Meta2Prefix, proto.KeyMax.Next()), true}, } for i, test := range testCases { err := ValidateRangeMetaKey(test.key) if err != nil != test.expErr { t.Errorf("%d: expected error? %t: %s", i, test.expErr, err) } } }
// MakeKey makes a new key which is the concatenation of the // given inputs, in order. func MakeKey(keys ...proto.Key) proto.Key { return proto.MakeKey(keys...) }
// // The resolution refers to the sample duration at which data is stored. // Cockroach supports a fixed set of named resolutions, which are stored in the // Resolution enumeration. This value is encoded as a VarInt in the key. // // Cockroach divides all data for a series into contiguous "time slots" of // uniform length based on the "key duration" of the Resolution. For each // series/source pair, there will be one key per slot. Slot 0 begins at unix // epoch; the slot for a specific timestamp is found by truncating the // timestamp to an exact multiple of the key duration, and then dividing it by // the key duration: // // slot := (timestamp / keyDuration) // integer division var ( // keyDataPrefix is the key prefix for time series data keys. keyDataPrefix = proto.MakeKey(keys.SystemPrefix, proto.Key("tsd")) ) // MakeDataKey creates a time series data key for the given series name, source, // Resolution and timestamp. The timestamp is expressed in nanoseconds since the // epoch; it will be truncated to an exact multiple of the supplied // Resolution's KeyDuration. func MakeDataKey(name string, source string, r Resolution, timestamp int64) proto.Key { // Normalize timestamp into a timeslot before recording. timeslot := timestamp / r.KeyDuration() k := append(proto.Key(nil), keyDataPrefix...) k = encoding.EncodeBytes(k, []byte(name)) k = encoding.EncodeVarint(k, int64(r)) k = encoding.EncodeVarint(k, timeslot) k = append(k, source...)
func TestMetaReverseScanBounds(t *testing.T) { defer leaktest.AfterTest(t) testCases := []struct { key, expStart, expEnd proto.Key expError string }{ { key: proto.Key{}, expStart: nil, expEnd: nil, expError: "KeyMin and Meta1Prefix can't be used as the key of reverse scan", }, { key: Meta1Prefix, expStart: nil, expEnd: nil, expError: "KeyMin and Meta1Prefix can't be used as the key of reverse scan", }, { key: Meta2KeyMax.Next(), expStart: nil, expEnd: nil, expError: "body of meta key range lookup is", }, { key: Meta1KeyMax.Next(), expStart: nil, expEnd: nil, expError: "body of meta key range lookup is", }, { key: proto.MakeKey(Meta2Prefix, proto.Key("foo")), expStart: Meta2Prefix, expEnd: proto.MakeKey(Meta2Prefix, proto.Key("foo\x00")), expError: "", }, { key: proto.MakeKey(Meta1Prefix, proto.Key("foo")), expStart: Meta1Prefix, expEnd: proto.MakeKey(Meta1Prefix, proto.Key("foo\x00")), expError: "", }, { key: Meta2Prefix, expStart: Meta1Prefix, expEnd: Meta2Prefix.Next(), expError: "", }, { key: Meta2KeyMax, expStart: Meta2Prefix, expEnd: Meta2KeyMax.Next(), expError: "", }, } for i, test := range testCases { resStart, resEnd, err := MetaReverseScanBounds(test.key) if err != nil && !testutils.IsError(err, test.expError) { t.Errorf("expected error: %s ; got %s", test.expError, err) } else if err == nil && test.expError != "" { t.Errorf("expected error: %s", test.expError) } if !resStart.Equal(test.expStart) || !resEnd.Equal(test.expEnd) { t.Errorf("%d: range bounds %q-%q don't match expected bounds %q-%q for key %q", i, resStart, resEnd, test.expStart, test.expEnd, test.key) } } }