diff --git a/pkg/suggestion/grid_service_test.go b/pkg/suggestion/grid_service_test.go new file mode 100644 index 00000000000..30bbebff68a --- /dev/null +++ b/pkg/suggestion/grid_service_test.go @@ -0,0 +1,280 @@ +package suggestion + +import ( + "testing" + "reflect" + + api "github.com/kubeflow/katib/pkg/api" +) + +func getSampleParameterConfigs() []*api.ParameterConfig { + parameterConfigs := make([]*api.ParameterConfig, 0) + + config1 := &api.ParameterConfig { + Name: "config1", + ParameterType: api.ParameterType_INT, + Feasible: &api.FeasibleSpace{ + Max: "2", + Min: "1", + }, + } + config2 := &api.ParameterConfig { + Name: "config2", + ParameterType: api.ParameterType_DOUBLE, + Feasible: &api.FeasibleSpace{ + Max: "5.5", + Min: "3.5", + }, + } + config3 := &api.ParameterConfig { + Name: "config3", + ParameterType: api.ParameterType_CATEGORICAL, + Feasible: &api.FeasibleSpace{ + List: []string{"alpha", "beta", "gamma"}, + }, + } + + parameterConfigs = append(parameterConfigs, config1) + parameterConfigs = append(parameterConfigs, config2) + parameterConfigs = append(parameterConfigs, config3) + + return parameterConfigs +} + +func getSampleSuggestionParameter(pattern int) []*api.SuggestionParameter { + suggestParam := make([]*api.SuggestionParameter, 0) + + switch pattern { + case 1: + param1 := &api.SuggestionParameter { + Name: "DefaultGrid", + Value: "1", + } + param2 := &api.SuggestionParameter { + Name: "Iteration", + Value: "2", + } + param3 := &api.SuggestionParameter { + Name: "learning-rate", + Value: "3", + } + suggestParam = append(suggestParam, param1) + suggestParam = append(suggestParam, param2) + suggestParam = append(suggestParam, param3) + + case 2: + param := &api.SuggestionParameter { + Name: "DefaultGrid", + Value: "-1", + } + suggestParam = append(suggestParam, param) + } + return suggestParam +} + +func TestAllocInt(t *testing.T) { + s := &GridSuggestService{} + + min1 := 1 + max1 := 2 + reqnum1 := 1 + + exp1 := "1" + rtn1 := s.allocInt(min1, max1, reqnum1) + + if rtn1[0] != exp1 { + t.Errorf("expected [%v], but %v is returned",exp1, rtn1) + } + + min2 := 1 + max2 := 9 + reqnum2 := 5 + + exp2 := []string{"1", "3", "5", "7", "9"} + rtn2 := s.allocInt(min2, max2, reqnum2) + + for i := 0; i < 5; i++ { + if rtn2[i] != exp2[i] { + t.Errorf("expected Array[%v] = %v, but %v is returned", i, exp2[i], rtn2[i]) + } + } +} + +func TestAllocFloat(t *testing.T) { + s := &GridSuggestService{} + + min1 := 1.0 + max1 := 2.0 + reqnum1 := 1 + + exp1 := "1.0000" + rtn1 := s.allocFloat(min1, max1, reqnum1) + + if rtn1[0] != exp1 { + t.Errorf("expected [%v], but %v is returned",exp1, rtn1) + } + + min2 := 1.0 + max2 := 9.0 + reqnum2 := 5 + + exp2 := []string{"1.0000", "3.0000", "5.0000", "7.0000", "9.0000"} + rtn2 := s.allocFloat(min2, max2, reqnum2) + + for i := 0; i < 5; i++ { + if rtn2[i] != exp2[i] { + t.Errorf("expected Array[%v] = %v, but %v is returned", i, exp2[i], rtn2[i]) + } + } +} + +func TestAllocCat(t *testing.T) { + s := &GridSuggestService{} + + list := []string{"alpha", "beta", "gamma"} + reqnum1 := 1 + + exp1 := []string{"alpha"} + rtn1 := s.allocCat(list, reqnum1) + + if rtn1[0] != exp1[0] { + t.Errorf("exptected %v, but %v", rtn1, exp1) + } + + reqnum2 := 5 + exp2 := []string{"alpha", "alpha", "beta", "beta", "gamma"} + rtn2 := s.allocCat(list, reqnum2) + + for i := 0; i < 5; i++ { + if rtn2[i] != exp2[i] { + t.Errorf("expected Array[%v] = %v, but %v is returned", i, exp2[i], rtn2[i]) + } + } +} + +func TestSetP(t *testing.T) { + s := &GridSuggestService{} + + gci := 0 + p := make([][]*api.Parameter, 4) + pcs := getSampleParameterConfigs() + pg := make([][]string, 0) + pg = append(pg, []string{"1", "2"}) + pg = append(pg, []string{"3.5000", "5.5000"}) + + s.setP(gci, p, pg, pcs) + + exp := make([][]*api.Parameter, 0) + + p1 := &api.Parameter { + Name: "config1", + ParameterType: api.ParameterType_INT, + Value: "1", + } + p2 := &api.Parameter { + Name: "config1", + ParameterType: api.ParameterType_INT, + Value: "2", + } + p3 := &api.Parameter { + Name: "config2", + ParameterType: api.ParameterType_DOUBLE, + Value: "3.5000", + } + p4 := &api.Parameter { + Name: "config2", + ParameterType: api.ParameterType_DOUBLE, + Value: "5.5000", + } + exp = append(exp, []*api.Parameter{p1,p3}) + exp = append(exp, []*api.Parameter{p1,p4}) + exp = append(exp, []*api.Parameter{p2,p3}) + exp = append(exp, []*api.Parameter{p2,p4}) + + for i, rtn := range p { + if !reflect.DeepEqual(rtn, exp[i]) { + t.Errorf("expected %v, but %v is returned", exp[i], rtn) + } + } +} + +func TestParseSuggestParam(t *testing.T) { + s := &GridSuggestService{} + + sp1 := getSampleSuggestionParameter(1) + rtn_defaultGrid1, rtn_i, rtn_ret := s.parseSuggestParam(sp1) + exp_defaultGrid1, exp_i := 1, 2 + exp_ret := make(map[string]int) + exp_ret["learning-rate"] = 3 + + if rtn_defaultGrid1 != exp_defaultGrid1 { + t.Errorf("expected DefaultGrid is %v, but %v is returned", exp_defaultGrid1, rtn_defaultGrid1) + } + if rtn_i != exp_i { + t.Errorf("expected Iteration is %v, but %v is returned", exp_i, rtn_i) + } + if !reflect.DeepEqual(rtn_ret, exp_ret) { + t.Errorf("expected parameter is %v, but %v is returned", exp_ret, rtn_ret) + } + + sp2 := getSampleSuggestionParameter(2) + rtn_defaultGrid2, _, _ := s.parseSuggestParam(sp2) + exp_defaultGrid2 := 1 + + if rtn_defaultGrid2 != exp_defaultGrid2 { + t.Errorf("expected DefaultGrid is %v, but %v is returned", exp_defaultGrid2, rtn_defaultGrid2) + } +} + +func TestGenGrids(t *testing.T) { + s := &GridSuggestService{} + + studyID := "testStudy" + pcs := getSampleParameterConfigs() + df := 1 + glist := make(map[string]int) + glist["config1"] = 2 + glist["config2"] = 3 + glist["config3"] = 3 + + rtn := s.genGrids(studyID, pcs, df, glist) + + exp_len := 1 + for _, v := range glist { + exp_len *= v + } + if len(rtn) != exp_len { + t.Errorf("expected %v parameters generated, but %v parameters generated", exp_len, len(rtn)) + } + + config1 := []string{"1", "2"} + config2 := []string{"3.5000", "4.5000", "5.5000"} + config3 := []string{"alpha", "beta", "gamma"} + iter := 0 + for _, c1 := range config1 { + for _, c2 := range config2 { + for _, c3 := range config3 { + exp_struct1 := &api.Parameter{ + Name: "config1", + ParameterType: api.ParameterType_INT, + Value: c1, + } + exp_struct2 := &api.Parameter{ + Name: "config2", + ParameterType: api.ParameterType_DOUBLE, + Value: c2, + } + exp_struct3 := &api.Parameter{ + Name: "config3", + ParameterType: api.ParameterType_CATEGORICAL, + Value: c3, + } + exp := []*api.Parameter{exp_struct1, exp_struct2, exp_struct3} + if !reflect.DeepEqual(rtn[iter], exp) { + t.Errorf("expected %v, but %v is returned", exp, rtn[iter]) + } + iter++ + } + } + } +} diff --git a/pkg/suggestion/hyperband_service_test.go b/pkg/suggestion/hyperband_service_test.go new file mode 100644 index 00000000000..2c659cdbe05 --- /dev/null +++ b/pkg/suggestion/hyperband_service_test.go @@ -0,0 +1,574 @@ +package suggestion + +import ( + "context" + "testing" + "strconv" + "reflect" + + "github.com/golang/mock/gomock" + + api "github.com/kubeflow/katib/pkg/api" + mockapi "github.com/kubeflow/katib/pkg/mock/api" +) + +func getSampleBracket(size int) Bracket { + sample := []Evals{} + for i := 0; i < size; i++ { + sample = append (sample, Evals{ id: "test" + strconv.Itoa(i+1), value: float64(i+1),}) + } + return sample +} + +func getSampleHyperBandParameters() HyperBandParameters { + sample := HyperBandParameters{ + eta:4.0, + sMax:100, + bL:60.0, + rL:30.0, + r:8.0, + n:50, + shloopitr:2, + currentS:3, + ResourceName:"testResource", + ObjectiveValueName:"testValue", + evaluatingTrials:[]string{"trial1", "trial2", "trial3"}, + } + return sample +} + +func getSampleStudyReply() *api.GetStudyReply { + fs := &api.FeasibleSpace { + Max:"10", + Min:"1", + List:[]string{"alpha","beta"}, + } + c1 := &api.ParameterConfig { + Name:"config1", + ParameterType:2, + Feasible:fs, + } + c2 := &api.ParameterConfig { + Name:"config2", + ParameterType:2, + Feasible:fs, + } + sp := []*api.ParameterConfig{c1, c2} + scpc := &api.StudyConfig_ParameterConfigs { + Configs:sp, + } + sc := &api.StudyConfig { + OptimizationType:1, + ParameterConfigs:scpc, + } + srep := &api.GetStudyReply { + StudyConfig:sc, + } + + return srep +} + +func getSampleTrialsReply() *api.GetTrialsReply { + t1 := &api.Trial { + TrialId:"trialId1", + } + t2 := &api.Trial { + TrialId:"trialId2", + } + ts := []*api.Trial{t1, t2} + trep := &api.GetTrialsReply { + Trials:ts, + } + + return trep +} + +func getExpectedTrials(n int) ([]string, []*api.Trial){ + exp_tids := []string{"trialId", "trialId"} + exp_ts := make([]*api.Trial, n) + parameter1 := &api.Parameter { + Name:"config1", + ParameterType:1, + Value:"1.0", + } + parameter2 := &api.Parameter { + Name:"config2", + ParameterType:2, + Value:"1", + } + parameter3 := &api.Parameter { + Name:"config3", + ParameterType:4, + Value:"test", + } + parameterSet := []*api.Parameter{parameter1, parameter2, parameter3} + trial := &api.Trial { + TrialId:"trialId", + StudyId:"studyId", + ParameterSet:parameterSet, + } + for i := range exp_ts { + exp_ts[i] = trial + } + + return exp_tids, exp_ts +} + +func getSampleSuggestionParameters() []*api.SuggestionParameter { + exp_sparam := make([]*api.SuggestionParameter, 0) + + eta := &api.SuggestionParameter { + Name:"eta", + Value:"1.5", + } + exp_sparam = append(exp_sparam, eta) + r_l := &api.SuggestionParameter { + Name:"r_l", + Value:"10.5", + } + exp_sparam = append(exp_sparam, r_l) + ResourceName := &api.SuggestionParameter { + Name:"ResourceName", + Value:"testResourceName", + } + exp_sparam = append(exp_sparam, ResourceName) + ObjectiveValueName := &api.SuggestionParameter { + Name:"ObjectiveValueName", + Value:"testObjectiveValueName", + } + exp_sparam = append(exp_sparam, ObjectiveValueName) + b_l := &api.SuggestionParameter { + Name:"b_l", + Value:"10.5", + } + exp_sparam = append(exp_sparam, b_l) + sMax := &api.SuggestionParameter { + Name:"sMax", + Value:"100", + } + exp_sparam = append(exp_sparam, sMax) + r := &api.SuggestionParameter { + Name:"r", + Value:"10.5", + } + exp_sparam = append(exp_sparam, r) + n := &api.SuggestionParameter { + Name:"n", + Value:"10", + } + exp_sparam = append(exp_sparam, n) + shloopitr := &api.SuggestionParameter { + Name:"shloopitr", + Value:"10", + } + exp_sparam = append(exp_sparam, shloopitr) + currentS := &api.SuggestionParameter { + Name:"currentS", + Value:"10", + } + exp_sparam = append(exp_sparam, currentS) + evaluatingTrials := &api.SuggestionParameter { + Name:"evaluatingTrials", + Value:"trial1,trial2,trial3", + } + exp_sparam = append(exp_sparam, evaluatingTrials) + + return exp_sparam +} + +func getSampleWorkersRequest() []*api.GetWorkersRequest { + wreq1 := &api.GetWorkersRequest { + StudyId:"studyId", + TrialId:"trial1", + } + wreq2 := &api.GetWorkersRequest { + StudyId:"studyId", + TrialId:"trial2", + } + wreq3 := &api.GetWorkersRequest { + StudyId:"studyId", + TrialId:"trial3", + } + wreq := []*api.GetWorkersRequest{wreq1, wreq2, wreq3} + + return wreq +} + +func getSampleWorkersReplyArray() []*api.GetWorkersReply { + worker1 := &api.Worker { + WorkerId:"worker1", + TrialId:"trial1", + } + worker2 := &api.Worker { + WorkerId:"worker2", + TrialId:"trial2", + } + worker3 := &api.Worker { + WorkerId:"worker3", + TrialId:"trial3", + } + wrep1 := &api.GetWorkersReply { + Workers:[]*api.Worker{worker1}, + } + wrep2 := &api.GetWorkersReply { + Workers:[]*api.Worker{worker2}, + } + wrep3 := &api.GetWorkersReply { + Workers:[]*api.Worker{worker3}, + } + wrep := []*api.GetWorkersReply{wrep1, wrep2, wrep3} + return wrep +} + +func getSampleMetricsRequestArray(ovn string) []*api.GetMetricsRequest { + metrics1 := &api.GetMetricsRequest { + StudyId:"studyId", + WorkerIds:[]string{"worker1"}, + MetricsNames:[]string{ovn}, + } + metrics2 := &api.GetMetricsRequest { + StudyId:"studyId", + WorkerIds:[]string{"worker2"}, + MetricsNames:[]string{ovn}, + } + metrics3 := &api.GetMetricsRequest { + StudyId:"studyId", + WorkerIds:[]string{"worker3"}, + MetricsNames:[]string{ovn}, + } + metrics := []*api.GetMetricsRequest{metrics1, metrics2, metrics3} + + return metrics +} + +func getSampleMetricsReplyArray() []*api.GetMetricsReply { + mvt := make([]*api.MetricsValueTime, 0) + for i := 0; i < 24; i++ { + mvt = append(mvt, &api.MetricsValueTime {Time: "Jan 1 12:00:00 2018 UTC", Value: strconv.Itoa(i),}) + } + + mLog := make([]*api.MetricsLog, 0) + for j := 0; j < 6; j++ { + mLog = append(mLog, &api.MetricsLog {Name: "metricsLog" + strconv.Itoa(j), Values: mvt[j*4:(j+1)*4],}) + } + + mLogSet := make([]*api.MetricsLogSet, 0) + for k := 0; k < 3; k++ { + mLogSet = append(mLogSet, &api.MetricsLogSet {WorkerId: "worker" + strconv.Itoa(k+1), MetricsLogs: mLog[k*2:(k+1)*2], WorkerStatus: 2}) + } + + mrepArray := make([]*api.GetMetricsReply, 0) + for l := 0; l < 3; l++ { + mrepArray = append(mrepArray, &api.GetMetricsReply {MetricsLogSets: []*api.MetricsLogSet{mLogSet[l],}}) + } + + return mrepArray +} + +func TestLen(t *testing.T) { + size := 2 + b := getSampleBracket(size) + exp := 2 + rtn := b.Len() + + if exp != rtn { + t.Errorf("expected %v, but returned %v", exp, rtn) + } +} + +func TestSwap(t *testing.T) { + size := 2 + b := getSampleBracket(size) + exp := Bracket{ + Evals{ + id:"test2", + value:2.0, + }, + Evals{ + id:"test1", + value:1.0, + }, + } + + b.Swap(0, 1) + + if exp[0] != b[0] || exp[1] != b[1] { + t.Errorf("expected %v, but returned %v", exp, b) + } +} + +func TestLess(t *testing.T) { + size := 2 + b := getSampleBracket(size) + exp := false + rtn := b.Less(0,1) + + if exp != rtn { + t.Errorf("expected %v, but returned %v", exp, rtn) + } +} + +func TestMakeMasterBracket(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + h := HyperBandSuggestService{} + mockAPI := mockapi.NewMockManagerClient(ctrl) + + sreq := &api.GetStudyRequest { + StudyId: "studyId", + } + srep := getSampleStudyReply() + mockAPI.EXPECT().GetStudy(context.Background(), sreq).Return(srep, nil) + + trep := &api.CreateTrialReply { + TrialId:"trialId", + } + mockAPI.EXPECT().CreateTrial(context.Background(), gomock.Any()).Return(trep, nil).AnyTimes() + + n := 3 + r := 2.0 + p := getSampleHyperBandParameters() + + exp_tids, exp_ts := getExpectedTrials(n) + rtn_tids, rtn_ts, err := h.makeMasterBracket(context.Background(), mockAPI, "studyId", n, r, &p) + if err != nil { + t.Errorf("makeMasterBracket Error: %v", err) + } + + for j := range exp_tids { + if exp_tids[j] != rtn_tids[j] { + t.Errorf("expected %v, but returned %v", exp_tids[j], rtn_tids[j]) + } + if exp_ts[j].TrialId != rtn_ts[j].TrialId || exp_ts[j].StudyId != rtn_ts[j].StudyId { + t.Errorf("expected %v, but returned %v", exp_ts[j], rtn_ts[j]) + } + } +} + +func TestMakeChildBracket(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + h := HyperBandSuggestService{} + mockAPI := mockapi.NewMockManagerClient(ctrl) + + sreq := &api.GetStudyRequest { + StudyId: "studyId", + + } + srep := getSampleStudyReply() + mockAPI.EXPECT().GetStudy(context.Background(), sreq).Return(srep, nil) + + treq := &api.GetTrialsRequest { + StudyId: "studyId", + } + strep := getSampleTrialsReply() + mockAPI.EXPECT().GetTrials(context.Background(), treq).Return(strep, nil) + + trep := &api.CreateTrialReply { + TrialId:"trialId", + } + mockAPI.EXPECT().CreateTrial(context.Background(), gomock.Any()).Return(trep, nil).AnyTimes() + + n := 3 + r := 2.0 + p := getSampleHyperBandParameters() + size := 10 + b := getSampleBracket(size) + exp_tids, exp_ts := getExpectedTrials(n) + rtn_tids, rtn_ts, err := h.makeChildBracket(context.Background(), mockAPI, b, "studyId", n, r, &p) + if err != nil { + t.Errorf("makeChildBracket Error: %v", err) + } + + for j := range exp_tids { + if exp_tids[j] != rtn_tids[j] { + t.Errorf("expected %v, but returned %v", exp_tids[j], rtn_tids[j]) + } + if exp_ts[j].TrialId != rtn_ts[j].TrialId || exp_ts[j].StudyId != rtn_ts[j].StudyId { + t.Errorf("expected %v, but returned %v", exp_ts[j], rtn_ts[j]) + } + } + +} + +func TestParseSuggestionParameters(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + h := HyperBandSuggestService{} + p1 := getSampleSuggestionParameters() + mockAPI := mockapi.NewMockManagerClient(ctrl) + + rtn_param1, _ := h.parseSuggestionParameters(context.Background(), mockAPI, "studyId", p1) + + exp_param1 := &HyperBandParameters{ + eta:1.5, + sMax:100, + bL:10.5, + rL:10.5, + r:10.5, + n:10, + shloopitr:10, + currentS:10, + ResourceName:"testResourceName", + ObjectiveValueName:"testObjectiveValueName", + evaluatingTrials:[]string{"trial1", "trial2", "trial3"}, + } + + if !reflect.DeepEqual(exp_param1, rtn_param1) { + t.Errorf("expected %v , but returned %v", exp_param1, rtn_param1) + } + + p2 := make([]*api.SuggestionParameter, 0) + rtn_param2, _ := h.parseSuggestionParameters(context.Background(), mockAPI, "studyId", p2) + + if rtn_param2 != nil { + t.Errorf("expected nil, but returned %v", rtn_param2) + } + + p3 := make([]*api.SuggestionParameter, 0) + r_l := &api.SuggestionParameter { + Name:"r_l", + Value:"27.0", + } + p3 = append(p3, r_l) + ResourceName := &api.SuggestionParameter { + Name:"ResourceName", + Value:"testResourceName", + } + p3 = append(p3, ResourceName) + sreq := &api.GetStudyRequest { + StudyId: "studyId", + } + srep := getSampleStudyReply() + mockAPI.EXPECT().GetStudy(context.Background(), sreq).Return(srep, nil) + rtn_param3, _ := h.parseSuggestionParameters(context.Background(), mockAPI, "studyId", p3) + + exp_param3 := &HyperBandParameters{ + eta:3, + sMax:3, + bL:108, + rL:27, + r:1, + n:27, + shloopitr:0, + currentS:3, + ResourceName:"testResourceName", + ObjectiveValueName:"", + evaluatingTrials:[]string{}, + } + if !reflect.DeepEqual(exp_param3, rtn_param3) { + t.Errorf("exptected %v, but returned %v", exp_param3, rtn_param3) + } +} + +func TestSaveSuggestionParameters(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + h := HyperBandSuggestService{} + p := getSampleHyperBandParameters() + mockAPI := mockapi.NewMockManagerClient(ctrl) + + mockAPI.EXPECT().SetSuggestionParameters(context.Background(), gomock.Any()).Return(nil, nil) + + rtn := h.saveSuggestionParameters(context.Background(), mockAPI, "studyID", "testAlgorithm", "paramID", &p) + + if rtn != nil { + t.Errorf("returned error: %v", rtn) + } +} + +func TestEvalWorkers(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + h := HyperBandSuggestService{} + p := getSampleHyperBandParameters() + mockAPI := mockapi.NewMockManagerClient(ctrl) + + wreq := getSampleWorkersRequest() + wrepArray := getSampleWorkersReplyArray() + + mockAPI.EXPECT().GetWorkers(context.Background(), wreq[0]).Return(wrepArray[0], nil) + mockAPI.EXPECT().GetWorkers(context.Background(), wreq[1]).Return(wrepArray[1], nil) + mockAPI.EXPECT().GetWorkers(context.Background(), wreq[2]).Return(wrepArray[2], nil) + + mreqArray := getSampleMetricsRequestArray(p.ObjectiveValueName) + mrep := getSampleMetricsReplyArray() + mockAPI.EXPECT().GetMetrics(context.Background(), mreqArray[0]).Return(mrep[0], nil) + mockAPI.EXPECT().GetMetrics(context.Background(), mreqArray[1]).Return(mrep[1], nil) + mockAPI.EXPECT().GetMetrics(context.Background(), mreqArray[2]).Return(mrep[2], nil) + + _, rtn_bracket := h.evalWorkers(context.Background(), mockAPI, "studyId", &p) + + + exp_bracket := []Evals{Evals{"trial3", 19,}, Evals{"trial2", 11,}, Evals{"trial1", 3,}} + + + for i, ebkt := range exp_bracket { + if ebkt != rtn_bracket[i] { + t.Errorf("Evals[%v]: expected %v, but returned %v", i, ebkt, rtn_bracket[i]) + } + } +} + +func TestHbLoopParamUpdate(t *testing.T) { + h := HyperBandSuggestService{} + p := getSampleHyperBandParameters() + + studyId := "testStudyId" + h.hbLoopParamUpdate(studyId, &p) + + exp := getSampleHyperBandParameters() + exp.r = 0.46875 + exp.n = 32 + exp.shloopitr = 0 + + if exp.r != p.r || exp.n != p.n || exp.shloopitr != p.shloopitr { + t.Errorf("expected %v, but returned %v", exp, p) + } +} + +func TestGetLoopParam(t *testing.T) { + h := HyperBandSuggestService{} + p := getSampleHyperBandParameters() + + studyId := "testStudyId" + n_i, r_i := h.getLoopParam(studyId, &p) + + exp_n_i, exp_r_i := 3, 128.0 + + if exp_n_i != n_i || exp_r_i != r_i { + t.Errorf("expected {%v %v}, but returned {%v %v}", exp_n_i, exp_r_i, n_i, r_i) + } +} + +func TestShLoopParamUpdate(t *testing.T) { + h := HyperBandSuggestService{} + p1 := getSampleHyperBandParameters() + + studyId := "testStudyId" + exp1 := p1.currentS + h.shLoopParamUpdate(studyId, &p1) + rtn1 := p1.currentS + + if exp1 != rtn1 { + t.Errorf("expected currentS = %v, but returned currentS = %v", exp1, rtn1) + } + + + p2 := getSampleHyperBandParameters() + p2.shloopitr = 100 + exp2 := p2.currentS + exp2-- + + h.shLoopParamUpdate(studyId, &p2) + rtn2 := p2.currentS + + if exp2 != rtn2 { + t.Errorf("expected currentS = %v, but returned currentS = %v", exp2, rtn2) + } +} diff --git a/pkg/suggestion/random_service_test.go b/pkg/suggestion/random_service_test.go new file mode 100644 index 00000000000..1475c021428 --- /dev/null +++ b/pkg/suggestion/random_service_test.go @@ -0,0 +1,42 @@ +package suggestion +import ( + "testing" +) +func TestDoubleRandom(t *testing.T) { + s := &RandomSuggestService{} + min1 := 1.0 + max1 := 1.0 + rtn1 := s.DoubleRandom(min1, max1) + exp1 := 1.0 + if rtn1 != exp1 { + t.Errorf("actual %v expected %v", rtn1, exp1) + } + min2 := 1.0 + max2 := 10.0 + var rtnA,rtnB float64 + for i := 0; i <= 10; i++ { + rtnA = s.DoubleRandom(min2, max2) + rtnB = s.DoubleRandom(min2, max2) + if rtnA != rtnB { + break + } else if i == 10 { + t.Errorf("different value is expected, but same value is returned %v = %v", rtnA, rtnB) + } + } +} +func TestIntRandom(t *testing.T) { + s := &RandomSuggestService{} + min := 1 + max := 10 + var rtnA,rtnB int + for i := 0; i <= 10; i++ { + rtnA = s.IntRandom(min, max) + rtnB = s.IntRandom(min, max) + + if rtnA != rtnB { + break + } else if i == 10 { + t.Errorf("different value is expected, but same value is returned %v = %v", rtnA, rtnB) + } + } +}