// readAllStateCommon reads and unmarshals (given a function) all state into a // list of core.State objects. // XXX: move this to some common file func readAllStateCommon(d core.StateDriver, baseKey string, sType core.State, unmarshal func([]byte, interface{}) error) ([]core.State, error) { stateType := reflect.TypeOf(sType) sliceType := reflect.SliceOf(stateType) values := reflect.MakeSlice(sliceType, 0, 1) byteValues, err := d.ReadAll(baseKey) if err != nil { return nil, err } for _, byteValue := range byteValues { value := reflect.New(stateType) err = unmarshal(byteValue, value.Interface()) if err != nil { return nil, err } values = reflect.Append(values, value.Elem()) } stateValues := []core.State{} for i := 0; i < values.Len(); i++ { // sanity checks if !values.Index(i).Elem().FieldByName("CommonState").IsValid() { return nil, core.Errorf("The state structure %v is missing core.CommonState", stateType) } //the following works as every core.State is expected to embed core.CommonState struct values.Index(i).Elem().FieldByName("CommonState").FieldByName("StateDriver").Set(reflect.ValueOf(d)) stateValue := values.Index(i).Interface().(core.State) stateValues = append(stateValues, stateValue) } return stateValues, nil }
func commonTestStateDriverWrite(t *testing.T, d core.StateDriver) { testBytes := []byte{0xb, 0xa, 0xd, 0xb, 0xa, 0xb, 0xe} key := "TestKeyRawWrite" err := d.Write(key, testBytes) if err != nil { t.Fatalf("failed to write bytes. Error: %s", err) } }
func commonTestStateDriverWriteState(t *testing.T, d core.StateDriver) { state := &testState{IgnoredField: d, IntField: 1234, StrField: "testString"} key := "testKey" err := d.WriteState(key, state, json.Marshal) if err != nil { t.Fatalf("failed to write state. Error: %s", err) } }
func commonTestStateDriverInitInvalidConfig(t *testing.T, d core.StateDriver) { config := &core.Config{} err := d.Init(config) if err == nil { t.Fatalf("d init succeeded, should have failed.") } err = d.Init(nil) if err == nil { t.Fatalf("d init succeeded, should have failed.") } }
func commonTestStateDriverInitInvalidConfig(t *testing.T, d core.StateDriver) { instInfo := core.InstanceInfo{DbURL: "xyz://127.0.0.1:2379"} err := d.Init(&instInfo) if err == nil { t.Fatalf("d init succeeded, should have failed.") } err = d.Init(nil) if err == nil { t.Fatalf("d init succeeded, should have failed.") } }
func commonTestStateDriverWatchAllStateModify(t *testing.T, d core.StateDriver) { state := &testState{IntField: 1234, StrField: "testString"} modState := &testState{IntField: 5678, StrField: "modString"} baseKey := "modify" key := baseKey + "/testKeyWatchAll" err := d.WriteState(key, state, json.Marshal) if err != nil { t.Fatalf("failed to write state. Error: %s", err) } defer func() { d.ClearState(key) }() recvErr := make(chan error, 1) stateCh := make(chan core.WatchState, 1) timer := time.After(waitTimeout) go func(rsps chan core.WatchState, retErr chan error) { err := d.WatchAllState(baseKey, state, json.Unmarshal, stateCh) if err != nil { retErr <- err return } }(stateCh, recvErr) // trigger modify after a slight pause to ensure that events are not missed time.Sleep(time.Second) err = d.WriteState(key, modState, json.Marshal) if err != nil { t.Fatalf("failed to write state. Error: %s", err) } for_label: for { select { case watchState := <-stateCh: s := watchState.Curr.(*testState) if s.IntField != modState.IntField || s.StrField != modState.StrField { t.Fatalf("Watch state mismatch. Expctd: %+v, Rcvd: %+v", modState, s) } if watchState.Prev == nil { t.Fatalf("Received a modify event without previous state value set.") } s = watchState.Prev.(*testState) if s.IntField != state.IntField || s.StrField != state.StrField { t.Fatalf("Watch state mismatch. Expctd: %+v, Rcvd: %+v", state, s) } break for_label case err := <-recvErr: t.Fatalf("Watch failed. Error: %s", err) break for_label case <-timer: t.Fatalf("timed out waiting for events") break for_label } } }
func commonTestStateDriverRead(t *testing.T, d core.StateDriver) { testBytes := []byte{0xb, 0xa, 0xd, 0xb, 0xa, 0xb, 0xe} key := "TestKeyRawRead" err := d.Write(key, testBytes) if err != nil { t.Fatalf("failed to write bytes. Error: %s", err) } readBytes, err := d.Read(key) if err != nil { t.Fatalf("failed to read bytes. Error: %s", err) } if !bytes.Equal(testBytes, readBytes) { t.Fatalf("read bytes don't match written bytes. Wrote: %v Read: %v", testBytes, readBytes) } }
func commonTestStateDriverReadState(t *testing.T, d core.StateDriver) { state := &testState{IgnoredField: d, IntField: 1234, StrField: "testString"} key := "contiv/dir1/testKeyRead" err := d.WriteState(key, state, json.Marshal) if err != nil { t.Fatalf("failed to write state. Error: %s", err) } readState := &testState{} err = d.ReadState(key, readState, json.Unmarshal) if err != nil { t.Fatalf("failed to read state. Error: %s", err) } if readState.IntField != state.IntField || readState.StrField != state.StrField { t.Fatalf("Read state didn't match state written. Wrote: %v Read: %v", state, readState) } }
func commonTestStateDriverReadStateAfterClear(t *testing.T, d core.StateDriver) { state := &testState{IntField: 1234, StrField: "testString"} key := "testKeyReadClear" err := d.WriteState(key, state, json.Marshal) if err != nil { t.Fatalf("failed to write state. Error: %s", err) } err = d.ClearState(key) if err != nil { t.Fatalf("failed to clear state. Error: %s", err) } readState := &testState{} err = d.ReadState(key, readState, json.Unmarshal) if err == nil { t.Fatalf("Able to read cleared state!. Key: %s, Value: %v", key, readState) } }