@Test(dataProvider = "hashEnabledValues")
  public void testOuterJoinWithNullOnBothSides(
      boolean parallelBuild, boolean probeHashEnabled, boolean buildHashEnabled) throws Exception {
    TaskContext taskContext = createTaskContext();

    // build
    RowPagesBuilder buildPages =
        rowPagesBuilder(buildHashEnabled, Ints.asList(0), ImmutableList.of(VARCHAR))
            .row("a")
            .row((String) null)
            .row((String) null)
            .row("a")
            .row("b");
    LookupSourceSupplier lookupSourceSupplier =
        buildHash(parallelBuild, taskContext, Ints.asList(0), buildPages);

    // probe
    List<Type> probeTypes = ImmutableList.<Type>of(VARCHAR);
    RowPagesBuilder probePages = rowPagesBuilder(probeHashEnabled, Ints.asList(0), probeTypes);
    List<Page> probeInput = probePages.row("a").row("b").row((String) null).row("c").build();
    OperatorFactory joinOperatorFactory =
        LookupJoinOperators.probeOuterJoin(
            0,
            new PlanNodeId("test"),
            lookupSourceSupplier,
            probePages.getTypes(),
            Ints.asList(0),
            probePages.getHashChannel());
    Operator joinOperator =
        joinOperatorFactory.createOperator(
            taskContext.addPipelineContext(true, true).addDriverContext());

    // expected
    MaterializedResult expected =
        MaterializedResult.resultBuilder(
                taskContext.getSession(), concat(probeTypes, buildPages.getTypes()))
            .row("a", "a")
            .row("a", "a")
            .row("b", "b")
            .row(null, null)
            .row("c", null)
            .build();

    assertOperatorEquals(
        joinOperator, probeInput, expected, true, getHashChannels(probePages, buildPages));
  }