blob: 1937b891f22d1dacb51a9702e7ab328f95234f66 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Unit tests for testing both MemStore and PersistentStore interfaces.
package storage
import (
"reflect"
"testing"
"time"
shufflerpb "cobalt"
)
// TestGetDayIndexUtc tests the utility function that computes day index for the
// stored observation.
func TestGetDayIndexUtc(t *testing.T) {
// test against difference in days
for i := 1; i <= 32; i++ {
testTime := time.Date(1970, time.January, i, 0, 0, 0, 0, time.UTC)
di := GetDayIndexUtc(testTime)
if int(di) != i-1 {
t.Errorf("got day index [%d], want day index [%d]", di, i-1)
}
}
// test against difference in hours
for i := 1; i <= 25; i++ {
testTime := time.Date(1970, time.January, 3, i, 0, 0, 0, time.UTC)
di := GetDayIndexUtc(testTime)
if i < 24 && di != uint32(2) {
t.Errorf("got day index [%d] for i:%d, want day index [2]", di, i)
}
if i > 24 && di != uint32(3) { // spills into next day
t.Errorf("got day index [%d] for i:%d, want day index [3]", di, i)
}
}
// test against difference in mins
for i := 1; i <= 128; i++ {
testTime := time.Date(1970, time.January, 3, 0, i, 0, 0, time.UTC)
di := GetDayIndexUtc(testTime)
if di != uint32(2) {
t.Errorf("got day index [%d] for time:%v, want day index [%d]", di, testTime, 2)
}
}
// test against difference in secs
for i := 0; i <= 86450; i += 3600 {
testTime := time.Date(1970, time.January, 3, 0, 0, i, 0, time.UTC)
di := GetDayIndexUtc(testTime)
if i < 86400 && di != uint32(2) {
t.Errorf("got day index [%d] for time:%v, want day index [%d]", di, testTime, 2)
} else if i >= 86400 && di != uint32(3) { // spills into next day
t.Errorf("got day index [%d] for time:%v, want day index [%d]", di, testTime, 3)
}
}
// test against leap years. In this example, there are 2 leap years in between
// 1970 and 1980 which accounts for 2 extra days in dayIndex.
testTime := time.Date(1980, time.January, 1, 0, 0, 0, 0, time.UTC)
di := GetDayIndexUtc(testTime)
if di != 3652 {
t.Errorf("got day index [%d] for time:%v, want day index [3652]", di, testTime)
}
}
// TestNewObservationVal verifies the constructor that builds |ObservationVal|.
func TestNewObservationVal(t *testing.T) {
eMsg := &shufflerpb.EncryptedMessage{
Scheme: shufflerpb.EncryptedMessage_NONE,
Ciphertext: []byte("ciphertext"),
}
testDayIndex := uint32(17201)
val := NewObservationVal(eMsg, "test", testDayIndex)
if val == nil {
t.Error("got empty ObservationVal")
}
// test arrival day index
if val.ArrivalDayIndex != testDayIndex {
t.Errorf("got day_index [%d], want day_index [%d]", val.ArrivalDayIndex, testDayIndex)
}
// test encrypted message
if eMsg != val.EncryptedObservation {
t.Errorf("got encrypted_message [%v], want encrypted_message [%v]", val.EncryptedObservation, eMsg)
}
// test id
if val.Id != "test" {
t.Errorf("got id [%v], want id [%v]", val.Id, "test")
}
}
// doTestAddGetAndDeleteObservations tests the Store methods
// AddAllObservations, GetObservations, GetNumObservations, GetKeys and
// DeleteValues.
func doTestAddGetAndDeleteObservations(t *testing.T, store Store) {
const numBatches = 10
const arrivalDayIndex = 16
// add observations for different metrics
batches := MakeObservationBatches(numBatches)
if err := store.AddAllObservations(batches, arrivalDayIndex); err != nil {
t.Errorf("AddAllObservations: got error %v, expected success", err)
}
var keys []*shufflerpb.ObservationMetadata
// verify each metadata bucket
for _, batch := range batches {
om := batch.GetMetaData()
keys = append(keys, om)
encMsgList := batch.GetEncryptedObservation()
CheckNumObservations(t, store, om, len(encMsgList))
CheckGetObservations(t, store, om, encMsgList)
}
// verify all keys
CheckKeys(t, store, keys)
// verify delete for metadata with MetricId=7
deleteMetricID := 7
om := batches[deleteMetricID].GetMetaData()
// Retrieve stored observation contents before deletion for metric 8
vals := CheckObservations(t, store, om, deleteMetricID+1)
// call delete for half the observations
deleteObVals := vals[0 : len(vals)/2]
if err := store.DeleteValues(om, deleteObVals); err != nil {
t.Errorf("DeleteValues: got error %v, expected successful deletion of obVals for metadata [%v]", err, om)
}
numValsAfterDeletion := len(vals) - len(deleteObVals)
var undeletedEMsgs []*shufflerpb.EncryptedMessage
for _, val := range vals[len(vals)/2:] {
undeletedEMsgs = append(undeletedEMsgs, val.EncryptedObservation)
}
// Verify deleted and stored observation contents after DeleteValues() call
CheckNumObservations(t, store, om, numValsAfterDeletion)
CheckDeleteObservations(t, store, om, numValsAfterDeletion, deleteObVals)
CheckGetObservations(t, store, om, undeletedEMsgs)
}
// doTestShuffle tests that the store returns shuffled observations for each
// key.
func doTestShuffle(t *testing.T, store Store) {
const numMsgs = 100
const arrivalDayIndex = 10
// Add one big single ObservationBatch
om := NewObservationMetaData(501)
batch := NewObservationBatchForMetadata(om, numMsgs)
if err := store.AddAllObservations([]*shufflerpb.ObservationBatch{batch},
arrivalDayIndex); err != nil {
t.Errorf("AddAllObservations: got error %v, expected success", err)
}
shuffledObVals := CheckObservations(t, store, om, numMsgs)
if len(shuffledObVals) == 0 {
t.Errorf("GetObservations() call failed for key: [%v]", om)
return
}
// extract emsgs from shuffledObVals
var shuffledEMsgs []*shufflerpb.EncryptedMessage
for _, obVal := range shuffledObVals {
shuffledEMsgs = append(shuffledEMsgs, obVal.EncryptedObservation)
}
// extract emsgs from original input batch
inputEMsgs := batch.GetEncryptedObservation()
shuffledCount := 0
for i := 0; i < numMsgs; i++ {
if !reflect.DeepEqual(inputEMsgs[i], shuffledEMsgs[i]) {
// observation got shuffled
shuffledCount++
}
}
// Check that basic shuffling occurred using some rough threshold.
if shuffledCount > 10 {
t.Logf("got [%v] shuffled observations out of [%d] total observations", shuffledCount, numMsgs)
}
}