Adding test cases for enter key press on buttons

Adding embedder test cases and pixel test for enter key press on check
box and radio buttons.

Bug: pdfium:1431
Change-Id: Ia8fb9658fa0770407fc9b044733aeb335814240f
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/66410
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/pwl/BUILD.gn b/fpdfsdk/pwl/BUILD.gn
index ea26c13..ea2ce94 100644
--- a/fpdfsdk/pwl/BUILD.gn
+++ b/fpdfsdk/pwl/BUILD.gn
@@ -50,6 +50,7 @@
   sources = [
     "cpwl_combo_box_embeddertest.cpp",
     "cpwl_edit_embeddertest.cpp",
+    "cpwl_special_button_embeddertest.cpp",
   ]
   deps = [
     ":pwl",
diff --git a/fpdfsdk/pwl/cpwl_special_button_embeddertest.cpp b/fpdfsdk/pwl/cpwl_special_button_embeddertest.cpp
new file mode 100644
index 0000000..bd6eea0
--- /dev/null
+++ b/fpdfsdk/pwl/cpwl_special_button_embeddertest.cpp
@@ -0,0 +1,147 @@
+// Copyright 2020 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "fpdfsdk/cpdfsdk_annot.h"
+#include "fpdfsdk/cpdfsdk_annotiterator.h"
+#include "fpdfsdk/cpdfsdk_formfillenvironment.h"
+#include "fpdfsdk/cpdfsdk_helpers.h"
+#include "fpdfsdk/formfiller/cffl_formfiller.h"
+#include "fpdfsdk/pwl/cpwl_special_button.h"
+#include "fpdfsdk/pwl/cpwl_wnd.h"
+#include "testing/embedder_test.h"
+
+class CPWLSpecialButtonEmbedderTest : public EmbedderTest {
+ protected:
+  void SetUp() override {
+    EmbedderTest::SetUp();
+    CreateAndInitializeFormPDF();
+  }
+
+  void TearDown() override {
+    UnloadPage(page_);
+    EmbedderTest::TearDown();
+  }
+
+  void CreateAndInitializeFormPDF() {
+    ASSERT_TRUE(OpenDocument("click_form.pdf"));
+
+    page_ = LoadPage(0);
+    ASSERT_TRUE(page_);
+
+    formfill_env_ = CPDFSDKFormFillEnvironmentFromFPDFFormHandle(form_handle());
+    CPDFSDK_AnnotIterator it(formfill_env_->GetPageView(0),
+                             CPDF_Annot::Subtype::WIDGET);
+
+    // Read only check box.
+    annot_readonly_checkbox_ = it.GetFirstAnnot();
+    ASSERT_TRUE(annot_readonly_checkbox_);
+    ASSERT_EQ(CPDF_Annot::Subtype::WIDGET,
+              annot_readonly_checkbox_->GetAnnotSubtype());
+
+    // Check box.
+    annot_checkbox_ = it.GetNextAnnot(annot_readonly_checkbox_);
+    ASSERT_TRUE(annot_checkbox_);
+    ASSERT_EQ(CPDF_Annot::Subtype::WIDGET, annot_checkbox_->GetAnnotSubtype());
+
+    // Read only radio button.
+    annot_readonly_radiobutton_ = it.GetNextAnnot(annot_checkbox_);
+    ASSERT_TRUE(annot_readonly_radiobutton_);
+    ASSERT_EQ(CPDF_Annot::Subtype::WIDGET,
+              annot_readonly_radiobutton_->GetAnnotSubtype());
+
+    // Tabbing three times from read only radio button to unselected normal
+    // radio button.
+    annot_radiobutton_ = annot_readonly_radiobutton_;
+    ASSERT_TRUE(annot_radiobutton_);
+    for (int i = 0; i < 3; i++) {
+      annot_radiobutton_ = it.GetNextAnnot(annot_radiobutton_);
+      ASSERT_TRUE(annot_radiobutton_);
+    }
+
+    ASSERT_EQ(CPDF_Annot::Subtype::WIDGET,
+              annot_radiobutton_->GetAnnotSubtype());
+  }
+
+  void FormFillerAndWindowSetup(CPDFSDK_Annot* annot) {
+    CFFL_InteractiveFormFiller* interactive_formfiller =
+        formfill_env_->GetInteractiveFormFiller();
+    {
+      ObservedPtr<CPDFSDK_Annot> observed(annot);
+      EXPECT_TRUE(interactive_formfiller->OnSetFocus(&observed, 0));
+    }
+
+    form_filler_ = interactive_formfiller->GetFormFillerForTesting(annot);
+    ASSERT_TRUE(form_filler_);
+
+    window_ = form_filler_->GetPWLWindow(formfill_env_->GetPageView(0), true);
+    ASSERT_TRUE(window_);
+  }
+
+  CPDFSDK_Annot* GetCPDFSDKAnnotCheckBox() const { return annot_checkbox_; }
+  CPDFSDK_Annot* GetCPDFSDKAnnotReadOnlyCheckBox() const {
+    return annot_readonly_checkbox_;
+  }
+  CPDFSDK_Annot* GetCPDFSDKAnnotRadioButton() const {
+    return annot_radiobutton_;
+  }
+  CPDFSDK_Annot* GetCPDFSDKAnnotReadOnlyRadioButton() const {
+    return annot_readonly_radiobutton_;
+  }
+  CPDFSDK_FormFillEnvironment* GetCPDFSDKFormFillEnv() const {
+    return formfill_env_;
+  }
+  CPWL_Wnd* GetWindow() const { return window_; }
+
+ private:
+  FPDF_PAGE page_;
+  CFFL_FormFiller* form_filler_;
+  CPDFSDK_Annot* annot_checkbox_;
+  CPDFSDK_Annot* annot_readonly_checkbox_;
+  CPDFSDK_Annot* annot_radiobutton_;
+  CPDFSDK_Annot* annot_readonly_radiobutton_;
+  CPDFSDK_FormFillEnvironment* formfill_env_;
+  CPWL_Wnd* window_;
+};
+
+TEST_F(CPWLSpecialButtonEmbedderTest, EnterOnReadOnlyCheckBox) {
+  FormFillerAndWindowSetup(GetCPDFSDKAnnotReadOnlyCheckBox());
+  CPWL_CheckBox* check_box = static_cast<CPWL_CheckBox*>(GetWindow());
+  EXPECT_TRUE(GetCPDFSDKFormFillEnv()->GetInteractiveFormFiller()->OnChar(
+      GetCPDFSDKAnnotReadOnlyCheckBox(), '\r', 0));
+  // The check box is checked by default. Since it is a read only checkbox,
+  // clicking Enter shouldn't change its state.
+  // TODO(http://crbug.com/pdfium/1431) : Change this to EXPECT_TRUE
+  // as part of the fix.
+  EXPECT_FALSE(check_box->IsChecked());
+}
+
+TEST_F(CPWLSpecialButtonEmbedderTest, EnterOnCheckBox) {
+  FormFillerAndWindowSetup(GetCPDFSDKAnnotCheckBox());
+  CPWL_CheckBox* check_box = static_cast<CPWL_CheckBox*>(GetWindow());
+  EXPECT_TRUE(GetCPDFSDKFormFillEnv()->GetInteractiveFormFiller()->OnChar(
+      GetCPDFSDKAnnotCheckBox(), '\r', 0));
+  EXPECT_TRUE(check_box->IsChecked());
+
+  EXPECT_TRUE(GetCPDFSDKFormFillEnv()->GetInteractiveFormFiller()->OnChar(
+      GetCPDFSDKAnnotCheckBox(), '\r', 0));
+  EXPECT_FALSE(check_box->IsChecked());
+}
+
+TEST_F(CPWLSpecialButtonEmbedderTest, EnterOnReadOnlyRadioButton) {
+  FormFillerAndWindowSetup(GetCPDFSDKAnnotReadOnlyRadioButton());
+  CPWL_RadioButton* radio_button = static_cast<CPWL_RadioButton*>(GetWindow());
+  EXPECT_TRUE(GetCPDFSDKFormFillEnv()->GetInteractiveFormFiller()->OnChar(
+      GetCPDFSDKAnnotReadOnlyRadioButton(), '\r', 0));
+  // TODO(http://crbug.com/pdfium/1431) : Change this to EXPECT_FALSE
+  // as part of the fix.
+  EXPECT_TRUE(radio_button->IsChecked());
+}
+
+TEST_F(CPWLSpecialButtonEmbedderTest, EnterOnRadioButton) {
+  FormFillerAndWindowSetup(GetCPDFSDKAnnotRadioButton());
+  CPWL_RadioButton* radio_button = static_cast<CPWL_RadioButton*>(GetWindow());
+  EXPECT_TRUE(GetCPDFSDKFormFillEnv()->GetInteractiveFormFiller()->OnChar(
+      GetCPDFSDKAnnotRadioButton(), '\r', 0));
+  EXPECT_TRUE(radio_button->IsChecked());
+}
diff --git a/testing/resources/pixel/checkbox_radiobutton.evt b/testing/resources/pixel/checkbox_radiobutton.evt
new file mode 100644
index 0000000..6742beb
--- /dev/null
+++ b/testing/resources/pixel/checkbox_radiobutton.evt
@@ -0,0 +1,11 @@
+# Check the checkbox

+mousemove,145,220

+mousedown,left,145,220

+mouseup,left,145,220

+

+# Tab to radio button from checkbox

+keycode,9

+keycode,9

+

+# Press Enter to select radio button

+charcode,13
\ No newline at end of file
diff --git a/testing/resources/pixel/checkbox_radiobutton.in b/testing/resources/pixel/checkbox_radiobutton.in
new file mode 100644
index 0000000..59d73a2
--- /dev/null
+++ b/testing/resources/pixel/checkbox_radiobutton.in
@@ -0,0 +1,199 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /AcroForm <<
+    /Fields [5 0 R 6 0 R 7 0 R 9 0 R]
+  >>
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 300 300]
+  /Contents 4 0 R
+  /Annots [5 0 R 6 0 R 8 0 R 10 0 R]
+>>
+endobj
+{{object 4 0}} <<
+  {{streamlen}}
+>>
+stream
+q
+q
+1 w
+1 0 1 RG
+1 .752941 .796078 rg
+n 135.5 250.5 19 19 re B*
+Q
+q
+2 w
+.1 .1 .1 RG
+.8 .843 1 rg
+n 136 211 18 18 re B*
+Q
+q
+2 w
+0 .501961 0 RG
+0 0 1 rg
+n
+104 110 m
+104 114.9706 99.97056 119 95 119 c
+90.02944 119 86 114.9706 86 110 c
+86 105.0294 90.02944 101 95 101 c
+99.97056 101 104 105.0294 104 110 c
+B*
+Q
+q
+2 w
+0 .501961 0 RG
+0 0 1 rg
+n
+104 60 m
+104 64.97056 99.97056 69 95 69 c
+90.02944 69 86 64.97056 86 60 c
+86 55.02944 90.02944 51 95 51 c
+99.97056 51 104 55.02944 104 60 c
+B*
+Q
+Q
+endstream
+endobj
+{{object 5 0}} <<
+  /Type /Annot
+  /Subtype /Widget
+  /FT /Btn
+  /Ff 1
+  /Rect [135 250 155 270]
+  /T (readOnlyCheckbox)
+  /AP <<
+    /N <<
+      /Yes 11 0 R
+    >>
+  >>
+  /AS /Off
+>>
+endobj
+{{object 6 0}} <<
+  /Type /Annot
+  /Subtype /Widget
+  /FT /Btn
+  /Ff 2
+  /Rect [135 210 155 230]
+  /T (checkbox)
+  /AP <<
+    /N <<
+      /Yes 11 0 R
+    >>
+  >>
+  /AS /Off
+>>
+endobj
+{{object 7 0}} <<
+  /FT /Btn
+  /Ff 49153
+  /T (readOnlyRadioButton)
+  /Kids [8 0 R]
+>>
+endobj
+{{object 8 0}} <<
+  /Type /Annot
+  /Subtype /Widget
+  /FT /Btn
+  /Parent 7 0 R
+  /Rect [85 100 105 120]
+  /AP <<
+    /N <<
+      /value1 12 0 R
+    >>
+  >>
+  /AS /Off
+>>
+endobj
+{{object 9 0}} <<
+  /FT /Btn
+  /Ff 49154
+  /T (radioButton)
+  /Kids [10 0 R]
+>>
+endobj
+{{object 10 0}} <<
+  /Type /Annot
+  /Subtype /Widget
+  /FT /Btn
+  /Parent 9 0 R
+  /Rect [85 50 105 70]
+  /AP <<
+    /N <<
+      /value1 12 0 R
+    >>
+  >>
+  /AS /Off
+>>
+endobj
+{{object 11 0}} <<
+  /Type /XObject
+  /Subtype /Form
+  /FormType 1
+  /BBox [0 0 20 20]
+  {{streamlen}}
+>>
+stream
+q
+.1 .1 .1 rg .1 .1 .1 RG
+17.2 15.95145 m
+11.20694 10 l
+17.2 4.027746 l
+15.97225 2.8 l
+10 8.793064 l
+4.027746 2.8 l
+2.8 4.027746 l
+8.813873 10 l
+2.8 15.97225 l
+4.027746 17.2 l
+10 11.20694 l
+15.97225 17.2 l
+17.2 15.95145 l
+h
+f
+Q
+endstream
+endobj
+{{object 12 0}} <<
+  /Type /XObject
+  /Subtype /Form
+  /FormType 1
+  /BBox [0 0 20 20]
+  {{streamlen}}
+>>
+stream
+q
+1 .752941 .796078 rg 1 .752941 .796078 RG
+17.2 15.95145 m
+11.20694 10 l
+17.2 4.027746 l
+15.97225 2.8 l
+10 8.793064 l
+4.027746 2.8 l
+2.8 4.027746 l
+8.813873 10 l
+2.8 15.97225 l
+4.027746 17.2 l
+10 11.20694 l
+15.97225 17.2 l
+17.2 15.95145 l
+h
+f
+Q
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/checkbox_radiobutton_expected.pdf.0.png b/testing/resources/pixel/checkbox_radiobutton_expected.pdf.0.png
new file mode 100644
index 0000000..8baabb7
--- /dev/null
+++ b/testing/resources/pixel/checkbox_radiobutton_expected.pdf.0.png
Binary files differ