func TestGetServiceInfo(t *testing.T) {
	addr2, cleanup, err := testutil.CreatekRPCTestServer(&fakeDispatcher{[]string{"Foo", "Bar"}, nil}, "AnalyzerService")
	if err != nil {
		t.Fatalf("Registering analyzer service failed: %v", err)
	}
	defer cleanup()

	addr0, cleanup, err := testutil.CreatekRPCTestServer(&fakeDispatcher{nil, nil}, "AnalyzerService")
	if err != nil {
		t.Fatalf("Registering analyzer service failed: %v", err)
	}
	defer cleanup()

	addre, cleanup, err := testutil.CreatekRPCTestServer(&errDispatcher{}, "AnalyzerService")
	if err != nil {
		t.Fatalf("Registering analyzer service failed: %v", err)
	}
	defer cleanup()

	addrp, cleanup, err := testutil.CreatekRPCTestServer(&panicDispatcher{}, "AnalyzerService")
	if err != nil {
		t.Fatalf("Registering analyzer service failed: %v", err)
	}
	defer cleanup()

	tests := []struct {
		addrs  []string
		result map[string]strset.Set
	}{
		{[]string{addr0}, map[string]strset.Set{addr0: nil}},
		{[]string{addr2}, map[string]strset.Set{addr2: strset.New("Foo", "Bar")}},
		{[]string{addr0, addr2}, map[string]strset.Set{addr2: strset.New("Foo", "Bar"), addr0: nil}},
		{[]string{addrp, addr2}, map[string]strset.Set{addr2: strset.New("Foo", "Bar"), addrp: nil}},
		{[]string{addre, addr2}, map[string]strset.Set{addr2: strset.New("Foo", "Bar"), addre: nil}},
	}

	for _, test := range tests {
		driver := NewDriver(test.addrs, nil)
		info := driver.getAllServiceInfo()

		if len(test.result) != len(info) {
			t.Errorf("Incorrect number of results: got %v, want %v", info, test.result)
		}

		for addr, expectCats := range test.result {
			if !strset.Equal(info[strings.TrimPrefix(addr, "http://")].categories.ToSlice(), expectCats.ToSlice()) {
				t.Errorf("Incorrect categories for %s: got %v, want %v", addr, info[addr].categories, expectCats)
			}
		}
	}
}
func TestCallAllAnalyzers(t *testing.T) {
	dispatcher := &fakeDispatcher{categories: []string{"Foo", "Bar"}, files: []string{"dir1/A.h", "dir1/A.cc"}}
	addr, cleanup, err := testutil.CreatekRPCTestServer(dispatcher, "AnalyzerService")
	if err != nil {
		t.Fatalf("Registering analyzer service failed: %v", err)
	}
	defer cleanup()

	driver := NewTestDriver([]serviceInfo{
		serviceInfo{addr, strset.New("Foo", "Bar"), ctxpb.Stage_PRE_BUILD},
	})

	tests := []struct {
		files      []string
		categories []string
		expect     []*notepb.Note
	}{
		{
			// - SomeOtherCategory should be dropped; if it weren't fakeDispatcher would return an error.
			// - fakeDispatcher produces notes for files we didn't ask about; they should be dropped.
			[]string{"dir1/A.cc"},
			[]string{"Foo", "SomeOtherCategory"},
			[]*notepb.Note{
				&notepb.Note{
					Category:    proto.String("Foo"),
					Description: proto.String(""),
					Location:    testutil.CreateLocation("dir1/A.cc"),
				},
			},
		},
	}
	for _, test := range tests {
		ctx := &ctxpb.ShipshapeContext{FilePath: test.files}

		ars := driver.callAllAnalyzers(strset.New(test.categories...), ctx, ctxpb.Stage_PRE_BUILD)
		var notes []*notepb.Note

		for _, ar := range ars {
			notes = append(notes, ar.Note...)
			if len(ar.Failure) > 0 {
				t.Errorf("Received failures from analyze call: %v", ar.Failure)
			}
		}

		ok, results := testutil.CheckNoteContainsContent(test.expect, notes)
		if !ok {
			t.Errorf("Incorrect notes for categories %v: %s\n got %v, want %v", test.categories, results, notes, test.expect)
		}
	}
}
func TestCallAllAnalyzersErrorCases(t *testing.T) {
	ctx := &ctxpb.ShipshapeContext{FilePath: []string{"dir1/A", "dir2/B"}}

	tests := []struct {
		response      *rpcpb.AnalyzeResponse
		expectNotes   []*notepb.Note
		expectFailure []*rpcpb.AnalysisFailure
	}{
		{ //analysis had a failure
			&rpcpb.AnalyzeResponse{
				Failure: []*rpcpb.AnalysisFailure{
					&rpcpb.AnalysisFailure{
						Category:       proto.String("Foo"),
						FailureMessage: proto.String("badbadbad"),
					},
				},
			},
			nil,
			[]*rpcpb.AnalysisFailure{
				&rpcpb.AnalysisFailure{
					Category:       proto.String("Foo"),
					FailureMessage: proto.String("badbadbad"),
				},
			},
		},
		{ //analysis had both failure and notes
			&rpcpb.AnalyzeResponse{
				Note: []*notepb.Note{
					&notepb.Note{
						Category:    proto.String("Foo"),
						Description: proto.String("A note"),
						Location:    testutil.CreateLocation("dir1/A"),
					},
					&notepb.Note{
						Category:    proto.String("Foo"),
						Description: proto.String("A note"),
						Location:    testutil.CreateLocation("dir1/A"),
					},
				},
				Failure: []*rpcpb.AnalysisFailure{
					&rpcpb.AnalysisFailure{
						Category:       proto.String("Foo"),
						FailureMessage: proto.String("badbadbad"),
					},
				},
			},
			[]*notepb.Note{
				&notepb.Note{
					Category:    proto.String("Foo"),
					Description: proto.String("A note"),
					Location:    testutil.CreateLocation("dir1/A"),
				},
				&notepb.Note{
					Category:    proto.String("Foo"),
					Description: proto.String("A note"),
					Location:    testutil.CreateLocation("dir1/A"),
				},
			},
			[]*rpcpb.AnalysisFailure{
				&rpcpb.AnalysisFailure{
					Category:       proto.String("Foo"),
					FailureMessage: proto.String("badbadbad"),
				},
			},
		},
	}
	for _, test := range tests {
		addr, cleanup, err := testutil.CreatekRPCTestServer(&fullFakeDispatcher{test.response}, "AnalyzerService")
		if err != nil {
			t.Fatalf("Registering analyzer service failed: %v", err)
		}
		defer cleanup()

		driver := NewTestDriver([]serviceInfo{
			serviceInfo{addr, strset.New("Foo"), ctxpb.Stage_PRE_BUILD},
		})

		ars := driver.callAllAnalyzers(strset.New("Foo"), ctx, ctxpb.Stage_PRE_BUILD)
		var notes []*notepb.Note
		var failures []*rpcpb.AnalysisFailure

		for _, ar := range ars {
			notes = append(notes, ar.Note...)
			failures = append(failures, ar.Failure...)
		}

		ok, results := testutil.CheckNoteContainsContent(test.expectNotes, notes)
		if !ok {
			t.Errorf("Incorrect notes for original response %v: %s\n got %v, want %v", test.response, results, notes, test.expectNotes)
		}
		ok, results = testutil.CheckFailureContainsContent(test.expectFailure, failures)
		if !ok {
			t.Errorf("Incorrect failures for original response %v: %s\n got %v, want %v", test.response, results, failures, test.expectFailure)
		}

	}
}