kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/storage/stream/stream_test.go (about)

     1  /*
     2   * Copyright 2016 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 stream
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"fmt"
    23  	"testing"
    24  
    25  	"kythe.io/kythe/go/platform/delimited"
    26  	"kythe.io/kythe/go/util/compare"
    27  
    28  	"google.golang.org/protobuf/encoding/protojson"
    29  	"google.golang.org/protobuf/proto"
    30  
    31  	cpb "kythe.io/kythe/proto/common_go_proto"
    32  	spb "kythe.io/kythe/proto/storage_go_proto"
    33  )
    34  
    35  func TestReader(t *testing.T) {
    36  	r := testBuffer(testEntries)
    37  
    38  	var i int
    39  	if err := NewReader(r)(func(e *spb.Entry) error {
    40  		if diff := compare.ProtoDiff(testEntries[i], e); diff != "" {
    41  			t.Errorf("testEntries[%d]: %s", i, diff)
    42  		}
    43  		i++
    44  		return nil
    45  	}); err != nil {
    46  		t.Fatal(err)
    47  	}
    48  
    49  	if i != len(testEntries) {
    50  		t.Fatalf("Missing %d entries", len(testEntries)-i)
    51  	}
    52  }
    53  
    54  func TestJSONReader(t *testing.T) {
    55  	r := testJSONBuffer(testEntries)
    56  
    57  	var i int
    58  	if err := NewJSONReader(r)(func(e *spb.Entry) error {
    59  		if diff := compare.ProtoDiff(testEntries[i], e); diff != "" {
    60  			t.Errorf("testEntries[%d]: %s", i, diff)
    61  		}
    62  		i++
    63  		return nil
    64  	}); err != nil {
    65  		t.Fatal(err)
    66  	}
    67  
    68  	if i != len(testEntries) {
    69  		t.Fatalf("Missing %d entries", len(testEntries)-i)
    70  	}
    71  }
    72  
    73  func TestStructuredEntry(t *testing.T) {
    74  	ms := &cpb.MarkedSource{PreText: "hi"}
    75  	pbms, err := proto.Marshal(ms)
    76  	if err != nil {
    77  		t.Fatalf("Error marshaling MarkedSource: %v", err)
    78  	}
    79  	entry := &spb.Entry{
    80  		Source:    &spb.VName{Signature: "sig"},
    81  		FactName:  "/kythe/code",
    82  		FactValue: pbms,
    83  	}
    84  	entryJSON, err := json.Marshal((*StructuredEntry)(entry))
    85  	if err != nil {
    86  		t.Fatalf("Error marshaling entry: %v", err)
    87  	}
    88  
    89  	var rawOut richJSONEntry
    90  	if err := json.Unmarshal(entryJSON, &rawOut); err != nil {
    91  		t.Fatalf("Error unmarshaling entry (without fact_value): %v", err)
    92  	}
    93  
    94  	var msOut cpb.MarkedSource
    95  	if err := protojson.Unmarshal(rawOut.FactValue, &msOut); err != nil {
    96  		t.Fatalf("Error unmarshaling fact_value: %v", err)
    97  	}
    98  
    99  	if !proto.Equal(ms, &msOut) {
   100  		t.Errorf("Failed to properly encode marked source:\n%s", rawOut.FactValue)
   101  	}
   102  
   103  	var entryOut StructuredEntry
   104  	if err := json.Unmarshal(entryJSON, &entryOut); err != nil {
   105  		t.Fatalf("Error unmarshaling StructuredEntry: %v", err)
   106  	}
   107  
   108  	if diff := compare.ProtoDiff(entry, (*spb.Entry)(&entryOut)); diff != "" {
   109  		t.Errorf("Roundtrip Marshal/Unmarshal failed: \n%v\n%v\n%s", entry, &entryOut, diff)
   110  	}
   111  }
   112  
   113  func BenchmarkReader(b *testing.B) {
   114  	buf := testBuffer(genEntries(b.N))
   115  	b.ResetTimer()
   116  	if err := NewReader(buf)(func(e *spb.Entry) error {
   117  		return nil
   118  	}); err != nil {
   119  		b.Fatal(err)
   120  	}
   121  }
   122  
   123  func BenchmarkJSONReader(b *testing.B) {
   124  	buf := testJSONBuffer(genEntries(b.N))
   125  	b.ResetTimer()
   126  	if err := NewJSONReader(buf)(func(e *spb.Entry) error {
   127  		return nil
   128  	}); err != nil {
   129  		b.Fatal(err)
   130  	}
   131  }
   132  
   133  func BenchmarkReaderChannel(b *testing.B) {
   134  	buf := testBuffer(genEntries(b.N))
   135  	b.ResetTimer()
   136  	for range ReadEntries(buf) {
   137  	}
   138  }
   139  
   140  func BenchmarkJSONReaderChannel(b *testing.B) {
   141  	buf := testJSONBuffer(genEntries(b.N))
   142  	b.ResetTimer()
   143  	for range ReadJSONEntries(buf) {
   144  	}
   145  }
   146  
   147  func testBuffer(entries []*spb.Entry) *bytes.Buffer {
   148  	buf := bytes.NewBuffer(nil)
   149  	wr := delimited.NewWriter(buf)
   150  	for _, e := range entries {
   151  		if err := wr.PutProto(e); err != nil {
   152  			panic(err)
   153  		}
   154  	}
   155  	return buf
   156  }
   157  
   158  func testJSONBuffer(entries []*spb.Entry) *bytes.Buffer {
   159  	buf := bytes.NewBuffer(nil)
   160  	for _, e := range entries {
   161  		rec, err := protojson.MarshalOptions{UseProtoNames: true}.Marshal(e)
   162  		if err != nil {
   163  			panic(err)
   164  		}
   165  		buf.Write(rec)
   166  	}
   167  	return buf
   168  }
   169  
   170  var testEntries = []*spb.Entry{
   171  	fact("node0", "kind", "test"),
   172  	edge("node0", "edge", "node1"),
   173  	fact("node1", "kind", "anotherTest"),
   174  	fact("blah", "blah", "eh"),
   175  }
   176  
   177  func genEntries(n int) []*spb.Entry {
   178  	entries := make([]*spb.Entry, n)
   179  	for i := 0; i < n; i++ {
   180  		if i%2 == 0 {
   181  			entries[i] = fact(fmt.Sprintf("node%d", i), "kind", "test")
   182  		} else {
   183  			entries[i] = edge(fmt.Sprintf("node%d", i-1), "edgeKind", fmt.Sprintf("node%d", i+1))
   184  		}
   185  	}
   186  	return entries
   187  }
   188  
   189  func fact(signature, factName, factValue string) *spb.Entry {
   190  	return &spb.Entry{
   191  		Source:    &spb.VName{Signature: signature},
   192  		FactName:  factName,
   193  		FactValue: []byte(factValue),
   194  	}
   195  }
   196  
   197  func edge(signature, edgeKind, targetSig string) *spb.Entry {
   198  	return &spb.Entry{
   199  		Source:   &spb.VName{Signature: signature},
   200  		EdgeKind: edgeKind,
   201  		Target:   &spb.VName{Signature: targetSig},
   202  		FactName: "/",
   203  	}
   204  }