[VOL-2043] : OLT Enable Test Case

- Added more test cases for OLT Enable. Now covers all scenarios.
- Fixed typos in unit test README.md

Change-Id: Ib931d89cedee78fe40ca67761a028365a047ebc3
diff --git a/.gitignore b/.gitignore
index 86addb2..da69683 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,7 +26,7 @@
 test_openolt
 
 # Test report
-**/openolt_test_results.xml
+**/test_openolt_report.xml
 
 # IntelliJ Files
 .idea
diff --git a/agent/src/core.cc b/agent/src/core.cc
index 9f30bde..9c27296 100644
--- a/agent/src/core.cc
+++ b/agent/src/core.cc
@@ -741,6 +741,7 @@
     bcmos_errno err;
     bcmolt_host_init_parms init_parms = {};
     init_parms.transport.type = BCM_HOST_API_CONN_LOCAL;
+    unsigned int failed_enable_device_cnt = 0;
 
     if (!state.is_activated()) {
 
@@ -808,7 +809,12 @@
                     }
                     err = bcmolt_oper_submit(dev_id, &oper.hdr);
                     if (err) {
+                        failed_enable_device_cnt ++;
                         OPENOLT_LOG(ERROR, openolt_log_id, "Enable PON device %d failed, err %d\n", dev, err);
+                        if (failed_enable_device_cnt == BCM_MAX_DEVS_PER_LINE_CARD) {
+                            OPENOLT_LOG(ERROR, openolt_log_id, "failed to enable all the pon ports\n");
+                            return Status(grpc::StatusCode::INTERNAL, "Failed to activate all PON ports");
+                        }
                     }
                     bcmos_usleep(200000);
                 }
diff --git a/agent/test/Makefile.in b/agent/test/Makefile.in
index bc8c91b..ffe5e3b 100644
--- a/agent/test/Makefile.in
+++ b/agent/test/Makefile.in
@@ -158,7 +158,7 @@
 	$(CXX) $(CXXFLAGS) $(CXXFLAGSDEVICE) -I../common -I./inc -I./device/$(OPENOLTDEVICE) -c $< -o $@
 
 test: all
-	./test_openolt --gtest_output="xml:./openolt_test_results.xml"
+	./test_openolt --gtest_output="xml:./test_openolt_report.xml"
 
 clean:
-	rm -f src/*.o lib/*.a ../src/*.o ../common/*.o ./test_openolt  ./openolt_test_results.xml
+	rm -f src/*.o lib/*.a ../src/*.o ../common/*.o ./test_openolt  ./test_openolt_report.xml
diff --git a/agent/test/README.md b/agent/test/README.md
index 137931d..1840e61 100644
--- a/agent/test/README.md
+++ b/agent/test/README.md
@@ -5,7 +5,7 @@
   - Google Test: https://github.com/google/googletest
   - C-Mock: https://github.com/hjagodzinski/C-Mock
  
-The goal of the unit tests for OpenOLT agent is to test is to test the OpenOLT application by stubbing and mocking the external interfaces, especially the BAL API and GRPC.
+The goal of the unit tests for OpenOLT agent is to test the OpenOLT application by stubbing and mocking the external interfaces, especially the BAL API and GRPC.
 
 # Building and Running Unit Test
 Follow the below steps to build and run unit test
@@ -21,13 +21,13 @@
 $ make test
 ```
 Once you have successfully built and run the unit-test, the test report will be available in `test_openolt_report.xml` file in `agent/test`.
-To clean all build artificats and test reports, do `make clean` in `agent/test`.
+To clean all build artifacts and test reports, do `make clean` in `agent/test`.
 
 # Adding new Unit Test Cases
 
 Before you add new test cases please read [GOOGLE TEST COOKBOOK](https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md) and [USING CMOCK](https://github.com/hjagodzinski/C-Mock/blob/master/README.md) to get acquainted with frameworks used for the unit-test cases.
 ## Create mocks, if needed
-Refer `agent/test/src/bal_mocker.cc` and `agent/test/src/bal_mocker.h` to see how mock functions are created (if needed by your test case). In the afore mentioned examples, mocks are created for certain BAL APIs.
+Refer `agent/test/src/bal_mocker.cc` and `agent/test/src/bal_mocker.h` to see how mock functions are created (if needed by your test case). In the aforementioned examples, mocks are created for certain BAL APIs.
 
 ## Create Unit Test Case
 Please refer example `agent/test/src/test_enable_olt.cc`.
diff --git a/agent/test/inc/bal_mocker.h b/agent/test/inc/bal_mocker.h
index 99be959..85bdb22 100644
--- a/agent/test/inc/bal_mocker.h
+++ b/agent/test/inc/bal_mocker.h
@@ -19,11 +19,22 @@
 #define __BAL_MOCKER_H__
 #include <cmock/cmock.h>
 #include <cstdlib>
+extern "C" {
+#include <bcmos_system.h>
+#include <bcmolt_api.h>
+#include <bcm_dev_log.h>
 #include "bcmos_errno.h"
-#include "bcmolt_host_api.h"
 #include "bcmolt_system_types_typedefs.h"
 #include "bcmolt_msg.h"
 
+/** Host subsystem initialization parameters */
+typedef struct bcmolt_host_init_parms
+{
+    int dummy;
+} bcmolt_host_init_parms;
+
+}
+
 class BalMocker : public CMockMocker<BalMocker>
 {
 public:
diff --git a/agent/test/src/bal_mocker.cc b/agent/test/src/bal_mocker.cc
index 5c89b03..b38906f 100644
--- a/agent/test/src/bal_mocker.cc
+++ b/agent/test/src/bal_mocker.cc
@@ -18,7 +18,8 @@
 
 
 #include "bal_mocker.h"
-
+extern "C" {
 CMOCK_MOCK_FUNCTION1(BalMocker, bcmolt_host_init, bcmos_errno(bcmolt_host_init_parms*));
 CMOCK_MOCK_FUNCTION2(BalMocker, bcmolt_cfg_get, bcmos_errno(bcmolt_oltid, bcmolt_cfg*));
 CMOCK_MOCK_FUNCTION2(BalMocker, bcmolt_oper_submit, bcmos_errno(bcmolt_oltid, bcmolt_oper*));
+}
diff --git a/agent/test/src/bal_stub.cc b/agent/test/src/bal_stub.cc
index 3119827..5ab1b79 100644
--- a/agent/test/src/bal_stub.cc
+++ b/agent/test/src/bal_stub.cc
@@ -144,11 +144,6 @@
     return BCM_ERR_OK;
 }
 
-bcmos_errno bcmolt_host_init(const bcmolt_host_init_parms *init_parms)
-{
-    return BCM_ERR_OK;
-}
-
 /* Map error code to error string */
 const char *bcmos_strerror(bcmos_errno err)
 {
diff --git a/agent/test/src/test_enable_olt.cc b/agent/test/src/test_enable_olt.cc
index db63606..0cdb965 100644
--- a/agent/test/src/test_enable_olt.cc
+++ b/agent/test/src/test_enable_olt.cc
@@ -56,3 +56,107 @@
     ASSERT_TRUE( olt_enable_res.error_message() == Status::OK.error_message() );
 }
 
+// Test 2: OltEnableFail_host_init_fail
+TEST_F(TestOltEnable, OltEnableFail_host_init_fail) {
+    // NiceMock is used to suppress 'WillByDefault' return errors on using 'NiceMock'.
+    // This is described in https://github.com/arangodb-helper/gtest/blob/master/googlemock/docs/CookBook.md
+    ::testing::NiceMock<BalMocker> balMock;
+    bcmos_errno host_init_res = BCM_ERR_INTERNAL;
+    bcmos_errno bal_cfg_get_res = BCM_ERR_NOT_CONNECTED;
+    bcmos_errno olt_oper_res = BCM_ERR_OK;
+
+    Status olt_enable_res;
+
+    // The 'EXPECT_CALL' will do strict validation of input parameters. This may not be relevant for
+    // the current test case. Use 'ON_CALL' instead.
+    // The ON_CALL results in WARNINGs when running tests. Use NickMock instead of directly using BalMocker.
+    // https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#the-nice-the-strict-and-the-naggy-nicestrictnaggy
+    // In below tests '::testing::_' does no validation on argument.
+    ON_CALL(balMock, bcmolt_host_init(::testing::_)).WillByDefault(::testing::Return(host_init_res));
+    ON_CALL(balMock, bcmolt_cfg_get(::testing::_,::testing::_)).WillByDefault(::testing::Return(bal_cfg_get_res));
+    ON_CALL(balMock, bcmolt_oper_submit(::testing::_, ::testing::_)).WillByDefault(::testing::Return(olt_oper_res));
+
+    olt_enable_res = Enable_(1, NULL);
+    ASSERT_TRUE( olt_enable_res.error_message() != Status::OK.error_message() );
+}
+
+// Test 3: OltEnableSuccess_PON_Device_Connected
+TEST_F(TestOltEnable, OltEnableSuccess_PON_Device_Connected) {
+    // NiceMock is used to suppress 'WillByDefault' return errors on using 'NiceMock'.
+    // This is described in https://github.com/arangodb-helper/gtest/blob/master/googlemock/docs/CookBook.md
+    ::testing::NiceMock<BalMocker> balMock;
+    bcmos_errno host_init_res = BCM_ERR_OK;
+    bcmos_errno bal_cfg_get_res = BCM_ERR_OK;
+
+    Status olt_enable_res;
+
+    // The 'EXPECT_CALL' will do strict validation of input parameters. This may not be relevant for
+    // the current test case. Use 'ON_CALL' instead.
+    // The ON_CALL results in WARNINGs when running tests. Use NickMock instead of directly using BalMocker.
+    // https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#the-nice-the-strict-and-the-naggy-nicestrictnaggy
+    // In below tests '::testing::_' does no validation on argument.
+    ON_CALL(balMock, bcmolt_host_init(::testing::_)).WillByDefault(::testing::Return(host_init_res));
+    ON_CALL(balMock, bcmolt_cfg_get(::testing::_,::testing::_)).WillByDefault(::testing::Return(bal_cfg_get_res));
+
+    olt_enable_res = Enable_(1, NULL);
+    ASSERT_TRUE( olt_enable_res.error_message() == Status::OK.error_message() );
+}
+
+// Test 4: OltEnableFail_All_PON_Enable_Fail
+TEST_F(TestOltEnable, OltEnableFail_All_PON_Enable_Fail) {
+    // NiceMock is used to suppress 'WillByDefault' return errors on using 'NiceMock'.
+    // This is described in https://github.com/arangodb-helper/gtest/blob/master/googlemock/docs/CookBook.md
+    ::testing::NiceMock<BalMocker> balMock;
+    bcmos_errno host_init_res = BCM_ERR_OK;
+    bcmos_errno bal_cfg_get_res = BCM_ERR_NOT_CONNECTED;
+    bcmos_errno olt_oper_res = BCM_ERR_INTERNAL;
+
+    Status olt_enable_res;
+
+    // Ensure that the state of the OLT is in deactivated to start with..
+    state.deactivate();
+
+    // The 'EXPECT_CALL' will do strict validation of input parameters. This may not be relevant for
+    // the current test case. Use 'ON_CALL' instead.
+    // The ON_CALL results in WARNINGs when running tests. Use NickMock instead of directly using BalMocker.
+    // https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#the-nice-the-strict-and-the-naggy-nicestrictnaggy
+    // In below tests '::testing::_' does no validation on argument.
+    ON_CALL(balMock, bcmolt_host_init(::testing::_)).WillByDefault(::testing::Return(host_init_res));
+    ON_CALL(balMock, bcmolt_cfg_get(::testing::_,::testing::_)).WillByDefault(::testing::Return(bal_cfg_get_res));
+    ON_CALL(balMock, bcmolt_oper_submit(::testing::_, ::testing::_)).WillByDefault(::testing::Return(olt_oper_res));
+
+    olt_enable_res = Enable_(1, NULL);
+    ASSERT_TRUE( olt_enable_res.error_message() != Status::OK.error_message() );
+}
+
+// Test 5 OltEnableSuccess_One_PON_Enable_Fail : One PON device enable fails, but all others succeed.
+TEST_F(TestOltEnable, OltEnableSuccess_One_PON_Enable_Fail) {
+    // NiceMock is used to suppress 'WillByDefault' return errors on using 'NiceMock'.
+    // This is described in https://github.com/arangodb-helper/gtest/blob/master/googlemock/docs/CookBook.md
+    ::testing::NiceMock<BalMocker> balMock;
+    bcmos_errno host_init_res = BCM_ERR_OK;
+    bcmos_errno bal_cfg_get_res = BCM_ERR_NOT_CONNECTED;
+    bcmos_errno olt_oper_res_fail = BCM_ERR_INTERNAL;
+    bcmos_errno olt_oper_res_success = BCM_ERR_OK;
+
+    Status olt_enable_res;
+
+    // Ensure that the state of the OLT is in deactivated to start with..
+    state.deactivate();
+
+    // The 'EXPECT_CALL' will do strict validation of input parameters. This may not be relevant for
+    // the current test case. Use 'ON_CALL' instead.
+    // The ON_CALL results in WARNINGs when running tests. Use NickMock instead of directly using BalMocker.
+    // https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#the-nice-the-strict-and-the-naggy-nicestrictnaggy
+    // In below tests '::testing::_' does no validation on argument.
+    ON_CALL(balMock, bcmolt_host_init(::testing::_)).WillByDefault(::testing::Return(host_init_res));
+    ON_CALL(balMock, bcmolt_cfg_get(::testing::_,::testing::_)).WillByDefault(::testing::Return(bal_cfg_get_res));
+    // For the the first PON mac device, the activation result will fail, and will succeed for all other PON mac devices.
+    EXPECT_CALL(balMock, bcmolt_oper_submit(::testing::_, ::testing::_))
+                         .WillOnce(::testing::Return(olt_oper_res_fail))
+                         .WillRepeatedly(::testing::Return(olt_oper_res_success));
+
+    olt_enable_res = Enable_(1, NULL);
+    // The OLT activation should succeed if at least one PON mac device activation succeeds.
+    ASSERT_TRUE( olt_enable_res.error_message() == Status::OK.error_message() );
+}