Beispiel #1
0
func TestReducer_EmptySplit(t *testing.T) {
	expectedPivot := testNode("blah", "test", "subkind", "input")

	// Input for a single node (pivot header only)
	in := testInput([]*ipb.Path{{
		Pivot: expectedPivot,
	}})

	var found *ipb.Path_Node
	out, err := reduce.Sort(ctx, in, &Reducer{
		Func: func(ctx context.Context, pivot *ipb.Path_Node, rio ReducerIO) error {
			sortKey, p, err := rio.Next()
			if err != io.EOF {
				t.Errorf("Unexpected return values: %q %v %v", sortKey, p, err)
			}
			if found != nil {
				t.Errorf("Already found pivot: %v", found)
			}
			found = pivot
			return nil
		},
	})
	if err != nil {
		t.Fatal(err)
	}

	if err := testutil.DeepEqual(expectedPivot, found); err != nil {
		t.Error(err)
	}

	if s, err := out.NextSplit(); err != io.EOF {
		t.Fatalf("Unexpected output/err: %v / %v", s, err)
	}
}
Beispiel #2
0
func BenchmarkReducer_Input(b *testing.B) {
	ps := []*ipb.Path{{
		Pivot: testNode("blah", "test", "subkind", "input"),
	}}

	for i := 0; i < b.N; i++ {
		ps = append(ps, &ipb.Path{
			Pivot: testNode("blah", "UNKNOWN"),
			Edges: testEdges(fmt.Sprintf("edgeKind.%d", i), fmt.Sprintf("target.%d", i)),
		})
	}

	in := testInput(ps)

	var readSplit bool
	b.ResetTimer()
	empty, err := reduce.Sort(ctx, in, &Reducer{
		OutputSort: func(p *ipb.Path) string {
			if len(p.Edges) == 0 {
				return ""
			}
			// Order by first edge's kind
			return p.Edges[0].Kind
		},
		Func: func(ctx context.Context, pivot *ipb.Path_Node, rio ReducerIO) error {
			if readSplit {
				b.Fatal("Multiple splits")
			}
			readSplit = true
			for {
				if _, _, err := rio.Next(); err == io.EOF {
					return nil
				} else if err != nil {
					return err
				}
			}
		},
	})
	if err != nil {
		b.Fatal(err)
	}

	if s, err := empty.NextSplit(); err != io.EOF {
		b.Fatalf("Unexpected output/err: %v / %v", s, err)
	}
}
Beispiel #3
0
func TestReducer_Input(t *testing.T) {
	in := testInput([]*ipb.Path{{
		Pivot: testNode("blah", "UNKNOWN"), // will be replaced by expectedPivot (below)
		Edges: testEdges("edgeKind", "target"),
	}, {
		Pivot: testNode("blah", "UNKNOWN2"), // will also be replaced
		Edges: testEdges("e1", "t1", "e2", "t2"),
	}, {
		// pivot-only edge will be sorted before anything else
		Pivot: testNode("blah", "test", "subkind", "input"),
	}, {
		Pivot: testNode("blah", "still UNKNOWN"), // replaced
		Edges: testEdges("e0", "t3"),
	}})

	var found []*ipb.Path
	empty, err := reduce.Sort(ctx, in, &Reducer{
		Func: func(ctx context.Context, pivot *ipb.Path_Node, rio ReducerIO) error {
			if len(found) > 0 {
				t.Fatalf("Already read paths: %v", found)
			}
			for {
				sortKey, p, err := rio.Next()
				if err == io.EOF {
					return nil
				} else if err != nil {
					t.Fatal(err)
				} else if sortKey != "" {
					t.Errorf("Unexpected sort key: %q", sortKey)
				} else if err := testutil.DeepEqual(pivot, p.Pivot); err != nil {
					t.Errorf("mismatched pivot: %v", err)
				}

				found = append(found, p)
			}
		},
	})
	if err != nil {
		t.Fatal(err)
	}

	expectedPivot := testNode("blah", "test", "subkind", "input")
	// Ordered the same as input
	expectedPaths := []*ipb.Path{{
		Pivot: expectedPivot,
		Edges: testEdges("edgeKind", "target"),
	}, {
		Pivot: expectedPivot,
		Edges: testEdges("e1", "t1", "e2", "t2"),
	}, {
		Pivot: expectedPivot,
		Edges: testEdges("e0", "t3"),
	}}

	if err := testutil.DeepEqual(expectedPaths, found); err != nil {
		t.Error(err)
	}

	if s, err := empty.NextSplit(); err != io.EOF {
		t.Fatalf("Unexpected output/err: %v / %v", s, err)
	}
}
Beispiel #4
0
func BenchmarkReducer_Output(b *testing.B) {
	in := testInput([]*ipb.Path{{
		Pivot: testNode("blah", "test", "subkind", "input"),
	}})

	var readSplit bool
	out, err := reduce.Sort(ctx, in, &Reducer{
		OutputSort: func(p *ipb.Path) string {
			if len(p.Edges) == 0 {
				return ""
			}
			// Order by first edge's kind
			return p.Edges[0].Kind
		},
		Func: func(ctx context.Context, pivot *ipb.Path_Node, rio ReducerIO) error {
			if readSplit {
				b.Fatal("Multiple splits")
			}
			readSplit = true
			// Pass-through the pivot node
			if err := rio.Emit(ctx, &ipb.Path{Pivot: pivot}); err != nil {
				b.Fatal(err)
			}
			if sortKey, p, err := rio.Next(); err != io.EOF {
				b.Fatalf("Unexpected input/err: %q %v %v", sortKey, p, err)
			}

			for i := 0; i < b.N; i++ {
				if err := rio.Emit(ctx, &ipb.Path{
					Pivot: pivot,
					Edges: testEdges(fmt.Sprintf("edgeKind.%d", i), fmt.Sprintf("target.%d", i)),
				}); err != nil {
					b.Fatal(err)
				}
			}
			return nil
		},
	})
	if err != nil {
		b.Fatal(err)
	}

	readSplit = false
	empty, err := reduce.Sort(ctx, out, &Reducer{
		Func: func(ctx context.Context, pivot *ipb.Path_Node, rio ReducerIO) error {
			if readSplit {
				b.Fatal("Multiple splits")
			}
			readSplit = true
			for {
				_, _, err := rio.Next()
				if err == io.EOF {
					return nil
				} else if err != nil {
					b.Fatal(err)
				}
			}
		},
	})

	if s, err := empty.NextSplit(); err != io.EOF {
		b.Fatalf("Unexpected output/err: %v / %v", s, err)
	}
}
Beispiel #5
0
func TestReducer_Output(t *testing.T) {
	in := testInput([]*ipb.Path{{
		Pivot: testNode("blah", "UNKNOWN"),
		Edges: testEdges("edgeKind", "target"),
	}, {
		Pivot: testNode("blah", "UNKNOWN2"),
		Edges: testEdges("e1", "t1", "e2", "t2"),
	}, {
		Pivot: testNode("blah", "test", "subkind", "input"),
	}, {
		Pivot: testNode("blah", "still UNKNOWN"),
		Edges: testEdges("e0", "t3"),
	}})

	out, err := reduce.Sort(ctx, in, &Reducer{
		OutputSort: func(p *ipb.Path) string {
			if len(p.Edges) == 0 {
				return ""
			}
			// Order by first edge's kind
			return p.Edges[0].Kind
		},
		Func: func(ctx context.Context, pivot *ipb.Path_Node, rio ReducerIO) error {
			// Pass-through the pivot node
			if err := rio.Emit(ctx, &ipb.Path{Pivot: pivot}); err != nil {
				t.Fatal(err)
			}
			for {
				_, p, err := rio.Next()
				if err == io.EOF {
					return nil
				} else if err != nil {
					t.Fatal(err)
				}
				// Pass-through each Path
				if err := rio.Emit(ctx, p); err != nil {
					t.Fatal(err)
				}
			}
		},
	})
	if err != nil {
		t.Fatal(err)
	}

	var found []*ipb.Path
	empty, err := reduce.Sort(ctx, out, &Reducer{
		Func: func(ctx context.Context, pivot *ipb.Path_Node, rio ReducerIO) error {
			if len(found) > 0 {
				t.Fatalf("Already read paths: %v", found)
			}
			for {
				_, p, err := rio.Next()
				if err == io.EOF {
					return nil
				} else if err != nil {
					t.Fatal(err)
				}
				found = append(found, p)
			}
		},
	})

	expectedPivot := testNode("blah", "test", "subkind", "input")

	// Ordered by first edge's kind
	expectedPaths := []*ipb.Path{{
		Pivot: expectedPivot,
		Edges: testEdges("e0", "t3"),
	}, {
		Pivot: expectedPivot,
		Edges: testEdges("e1", "t1", "e2", "t2"),
	}, {
		Pivot: expectedPivot,
		Edges: testEdges("edgeKind", "target"),
	}}

	if err := testutil.DeepEqual(expectedPaths, found); err != nil {
		t.Error(err)
	}

	if s, err := empty.NextSplit(); err != io.EOF {
		t.Fatalf("Unexpected output/err: %v / %v", s, err)
	}
}