kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/serving/xrefs/assemble/assemble_test.go (about)

     1  /*
     2   * Copyright 2015 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package assemble
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"kythe.io/kythe/go/test/testutil"
    24  
    25  	"google.golang.org/protobuf/proto"
    26  
    27  	ipb "kythe.io/kythe/proto/internal_go_proto"
    28  	srvpb "kythe.io/kythe/proto/serving_go_proto"
    29  	spb "kythe.io/kythe/proto/storage_go_proto"
    30  )
    31  
    32  func fact(name, value string) *spb.Entry {
    33  	return &spb.Entry{
    34  		FactName:  name,
    35  		FactValue: []byte(value),
    36  	}
    37  }
    38  
    39  func edge(kind, targetSig string) *spb.Entry {
    40  	return &spb.Entry{
    41  		EdgeKind: kind,
    42  		Target: &spb.VName{
    43  			Signature: targetSig,
    44  		},
    45  		FactName: "/",
    46  	}
    47  }
    48  
    49  func TestAppendEntry(t *testing.T) {
    50  	tests := []struct {
    51  		entries  []*spb.Entry
    52  		expected *ipb.Source
    53  	}{{
    54  		entries: []*spb.Entry{fact("fact", "value")},
    55  		expected: &ipb.Source{
    56  			Facts: map[string][]byte{"fact": []byte("value")},
    57  		},
    58  	}, {
    59  		entries: []*spb.Entry{edge("kind", "target")},
    60  		expected: &ipb.Source{
    61  			EdgeGroups: map[string]*ipb.Source_EdgeGroup{
    62  				"kind": {
    63  					Edges: []*ipb.Source_Edge{{Ticket: "kythe:#target"}},
    64  				},
    65  			},
    66  		},
    67  	}, {
    68  		entries: []*spb.Entry{
    69  			fact("kind", "first"),
    70  			fact("kind", "second"),
    71  			edge("edgeKind", "firstTarget"),
    72  			edge("edgeKind", "secondTarget"),
    73  			fact("blah", "blah"),
    74  		},
    75  		expected: &ipb.Source{
    76  			Facts: map[string][]byte{
    77  				"kind": []byte("second"),
    78  				"blah": []byte("blah"),
    79  			},
    80  			EdgeGroups: map[string]*ipb.Source_EdgeGroup{
    81  				"edgeKind": {
    82  					Edges: []*ipb.Source_Edge{{
    83  						Ticket: "kythe:#firstTarget",
    84  					}, {
    85  						Ticket: "kythe:#secondTarget",
    86  					}},
    87  				},
    88  			},
    89  		},
    90  	}}
    91  
    92  	for i, test := range tests {
    93  		src := &ipb.Source{
    94  			Facts:      make(map[string][]byte),
    95  			EdgeGroups: make(map[string]*ipb.Source_EdgeGroup),
    96  		}
    97  
    98  		for _, e := range test.entries {
    99  			AppendEntry(src, e)
   100  		}
   101  
   102  		if err := testutil.DeepEqual(test.expected, src); err != nil {
   103  			t.Errorf("tests[%d] error: %v", i, err)
   104  		}
   105  	}
   106  }
   107  
   108  var ctx = context.Background()
   109  
   110  type testESB struct {
   111  	*EdgeSetBuilder
   112  
   113  	PagedEdgeSets []*srvpb.PagedEdgeSet
   114  	EdgePages     []*srvpb.EdgePage
   115  }
   116  
   117  func newTestESB(esb *EdgeSetBuilder) *testESB {
   118  	if esb == nil {
   119  		esb = new(EdgeSetBuilder)
   120  	}
   121  
   122  	t := &testESB{
   123  		EdgeSetBuilder: esb,
   124  	}
   125  	t.Output = func(_ context.Context, pes *srvpb.PagedEdgeSet) error {
   126  		t.PagedEdgeSets = append(t.PagedEdgeSets, pes)
   127  		return nil
   128  	}
   129  	t.OutputPage = func(_ context.Context, pes *srvpb.EdgePage) error {
   130  		t.EdgePages = append(t.EdgePages, pes)
   131  		return nil
   132  	}
   133  	return t
   134  }
   135  
   136  func makeNodes() map[string]*srvpb.Node {
   137  	m := make(map[string]*srvpb.Node)
   138  	// TODO(schroederc): fill
   139  	return m
   140  }
   141  
   142  // TODO(schroederc): add some facts for each node
   143  var testNodes = makeNodes()
   144  
   145  func getEdgeTargets(tickets ...string) []*srvpb.EdgeGroup_Edge {
   146  	es := make([]*srvpb.EdgeGroup_Edge, len(tickets))
   147  	for i, t := range tickets {
   148  		es[i] = &srvpb.EdgeGroup_Edge{
   149  			Target: getNode(t),
   150  		}
   151  	}
   152  	return es
   153  }
   154  
   155  func getNode(t string) *srvpb.Node {
   156  	n, ok := testNodes[t]
   157  	if !ok {
   158  		n = &srvpb.Node{Ticket: t}
   159  	}
   160  	return n
   161  }
   162  
   163  func TestEdgeSetBuilder(t *testing.T) {
   164  	tests := []struct {
   165  		src       *srvpb.Node
   166  		grp       *srvpb.EdgeGroup
   167  		edgeSet   *srvpb.PagedEdgeSet
   168  		edgePages []*srvpb.EdgePage
   169  	}{{
   170  		src: getNode("someSource"),
   171  	}, {
   172  		grp: &srvpb.EdgeGroup{
   173  			Kind: "someEdgeKind",
   174  			Edge: getEdgeTargets("kythe:#aTarget"),
   175  		},
   176  	}, {
   177  		// flush
   178  		edgeSet: &srvpb.PagedEdgeSet{
   179  			Source: getNode("someSource"),
   180  			Group: []*srvpb.EdgeGroup{{
   181  				Kind: "someEdgeKind",
   182  				Edge: getEdgeTargets("kythe:#aTarget"),
   183  			}},
   184  			TotalEdges: 1,
   185  		},
   186  	}, {
   187  		src: getNode("someOtherSource"),
   188  	}, {
   189  		grp: &srvpb.EdgeGroup{
   190  			Kind: "someEdgeKind",
   191  			Edge: getEdgeTargets(
   192  				"kythe:#aTarget",
   193  				"kythe:#anotherTarget",
   194  			),
   195  		},
   196  	}, {
   197  		grp: &srvpb.EdgeGroup{
   198  			Kind: "someEdgeKind",
   199  			Edge: getEdgeTargets(
   200  				"kythe:#onceMoreWithFeeling",
   201  			),
   202  		},
   203  	}, {
   204  		src: getNode("aThirdSource"),
   205  
   206  		// forced flush due to new source
   207  		edgeSet: &srvpb.PagedEdgeSet{
   208  			Source: getNode("someOtherSource"),
   209  			Group: []*srvpb.EdgeGroup{{
   210  				Kind: "someEdgeKind",
   211  				Edge: getEdgeTargets(
   212  					"kythe:#aTarget",
   213  					"kythe:#anotherTarget",
   214  					"kythe:#onceMoreWithFeeling",
   215  				),
   216  			}},
   217  
   218  			TotalEdges: 3, // fits exactly MaxEdgePageSize
   219  		},
   220  	}, {
   221  		grp: &srvpb.EdgeGroup{
   222  			Kind: "edgeKind123",
   223  			Edge: getEdgeTargets("kythe:#aTarget"),
   224  		},
   225  	}, {
   226  		grp: &srvpb.EdgeGroup{
   227  			Kind: "edgeKind123",
   228  			Edge: getEdgeTargets(
   229  				"kythe:#bTarget",
   230  				"kythe:#anotherTarget",
   231  				"kythe:#threeTarget",
   232  				"kythe:#fourTarget",
   233  			),
   234  		},
   235  
   236  		edgePages: []*srvpb.EdgePage{{
   237  			SourceTicket: "aThirdSource",
   238  			PageKey:      "aThirdSource.0000000000",
   239  			EdgesGroup: &srvpb.EdgeGroup{
   240  				Kind: "edgeKind123",
   241  				Edge: getEdgeTargets(
   242  					"kythe:#aTarget",
   243  					"kythe:#bTarget",
   244  					"kythe:#anotherTarget",
   245  				),
   246  			},
   247  		}},
   248  	}, {
   249  		grp: &srvpb.EdgeGroup{
   250  			Kind: "edgeKind123",
   251  			Edge: getEdgeTargets(
   252  				"kythe:#five", "kythe:#six", "kythe:#seven", "kythe:#eight", "kythe:#nine",
   253  			),
   254  		},
   255  
   256  		edgePages: []*srvpb.EdgePage{{
   257  			SourceTicket: "aThirdSource",
   258  			PageKey:      "aThirdSource.0000000001",
   259  			EdgesGroup: &srvpb.EdgeGroup{
   260  				Kind: "edgeKind123",
   261  				Edge: getEdgeTargets(
   262  					"kythe:#threeTarget", "kythe:#fourTarget", "kythe:#five",
   263  				),
   264  			},
   265  		}, {
   266  			SourceTicket: "aThirdSource",
   267  			PageKey:      "aThirdSource.0000000002",
   268  			EdgesGroup: &srvpb.EdgeGroup{
   269  				Kind: "edgeKind123",
   270  				Edge: getEdgeTargets(
   271  					"kythe:#six", "kythe:#seven", "kythe:#eight",
   272  				),
   273  			},
   274  		}},
   275  	}, {
   276  		grp: &srvpb.EdgeGroup{
   277  			Kind: "edgeKind123",
   278  			Edge: getEdgeTargets(
   279  				"kythe:#ten", "kythe:#eleven",
   280  			),
   281  		},
   282  	}, {
   283  		grp: &srvpb.EdgeGroup{
   284  			Kind: "edgeKindFinal",
   285  			Edge: getEdgeTargets(
   286  				"kythe:#ten",
   287  			),
   288  		},
   289  
   290  		edgePages: []*srvpb.EdgePage{{
   291  			SourceTicket: "aThirdSource",
   292  			PageKey:      "aThirdSource.0000000003",
   293  			EdgesGroup: &srvpb.EdgeGroup{
   294  				Kind: "edgeKind123",
   295  				Edge: getEdgeTargets(
   296  					"kythe:#nine", "kythe:#ten", "kythe:#eleven",
   297  				),
   298  			},
   299  		}},
   300  	}, {
   301  		grp: &srvpb.EdgeGroup{
   302  			Kind: "edgeKindFinal",
   303  			Edge: getEdgeTargets(
   304  				"kythe:#two", "kythe:#three",
   305  			),
   306  		},
   307  	}, {
   308  		// flush
   309  
   310  		edgeSet: &srvpb.PagedEdgeSet{
   311  			TotalEdges: 15,
   312  
   313  			Source: getNode("aThirdSource"),
   314  			Group: []*srvpb.EdgeGroup{{
   315  				Kind: "edgeKindFinal",
   316  				Edge: getEdgeTargets(
   317  					"kythe:#ten", "kythe:#two", "kythe:#three",
   318  				),
   319  			}},
   320  
   321  			PageIndex: []*srvpb.PageIndex{{
   322  				PageKey:   "aThirdSource.0000000000",
   323  				EdgeKind:  "edgeKind123",
   324  				EdgeCount: 3,
   325  			}, {
   326  				PageKey:   "aThirdSource.0000000001",
   327  				EdgeKind:  "edgeKind123",
   328  				EdgeCount: 3,
   329  			}, {
   330  				PageKey:   "aThirdSource.0000000002",
   331  				EdgeKind:  "edgeKind123",
   332  				EdgeCount: 3,
   333  			}, {
   334  				PageKey:   "aThirdSource.0000000003",
   335  				EdgeKind:  "edgeKind123",
   336  				EdgeCount: 3,
   337  			}},
   338  		},
   339  	}}
   340  
   341  	tESB := newTestESB(&EdgeSetBuilder{
   342  		MaxEdgePageSize: 3,
   343  	})
   344  	var edgeSets, edgePages int
   345  	for _, test := range tests {
   346  		if test.src != nil {
   347  			testutil.Fatalf(t, "Failure to StartEdgeSet: %v",
   348  				tESB.StartEdgeSet(ctx, test.src))
   349  		} else if test.grp != nil {
   350  			testutil.Fatalf(t, "Failure to AddGroup: %v",
   351  				tESB.AddGroup(ctx, test.grp))
   352  		} else {
   353  			testutil.Fatalf(t, "Failure to Flush: %v",
   354  				tESB.Flush(ctx))
   355  		}
   356  
   357  		if test.edgeSet != nil {
   358  			// Expected a new PagedEdgeSet
   359  			if edgeSets+1 != len(tESB.PagedEdgeSets) {
   360  				t.Fatalf("Missing expected PagedEdgeSet: %v", test.edgeSet)
   361  			} else if found := tESB.PagedEdgeSets[len(tESB.PagedEdgeSets)-1]; !proto.Equal(test.edgeSet, found) {
   362  				t.Errorf("Expected PagedEdgeSet: %v; found: %v", test.edgeSet, found)
   363  			}
   364  			edgeSets++
   365  		} else if edgeSets != len(tESB.PagedEdgeSets) {
   366  			t.Fatalf("Unexpected PagedEdgeSet: %v", tESB.PagedEdgeSets[len(tESB.PagedEdgeSets)-1])
   367  		}
   368  
   369  		// Expected new EdgePage(s)
   370  		for i := 0; i < len(test.edgePages); i++ {
   371  			if edgePages >= len(tESB.EdgePages) {
   372  				t.Fatalf("Missing expected EdgePages: %v", test.edgePages[i])
   373  			} else if err := testutil.DeepEqual(test.edgePages[i], tESB.EdgePages[edgePages]); err != nil {
   374  				t.Error(err)
   375  			}
   376  			edgePages++
   377  		}
   378  		if edgePages != len(tESB.EdgePages) {
   379  			t.Fatalf("Unexpected EdgePage(s): %v", tESB.EdgePages[edgePages:])
   380  		}
   381  	}
   382  }