text: // Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
  //
  // This Source Code Form is subject to the terms of the Mozilla Public
  // License, v. 2.0. If a copy of the MPL was not distributed with this
  // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  
  #include <config.h>
  
  #include <yang/tests/yang_configs.h>
  
  #include <gtest/gtest.h>
  #include <sstream>
  
  using namespace std;
  using namespace isc;
  using namespace isc::yang;
  using namespace isc::yang::test;
  #ifndef HAVE_PRE_0_7_6_SYSREPO
  using namespace sysrepo;
  #endif
  
  namespace {
  
  // Test sr_type_t print.
  TEST(YangReprTest, type) {
      ostringstream os;
  
      // Verify that string is "string" (vs a number).
      sr_type_t t = SR_STRING_T;
      os << t;
      EXPECT_EQ("string", os.str());
      os.str("");
  
      // Compiler does not let to create an invalid value...
  }
  
  // Test YangReprItem basic stuff.
  TEST(YangReprTest, item) {
      // An item.
      YRItem item1("/foo", "bar", SR_STRING_T, true);
      EXPECT_EQ("/foo", item1.xpath_);
      EXPECT_EQ("bar", item1.value_);
      EXPECT_EQ(SR_STRING_T, item1.type_);
      EXPECT_TRUE(item1.settable_);
  
      // Another one.
      YRItem item2("/foo", "bar", SR_STRING_T, false);
      EXPECT_EQ("/foo", item2.xpath_);
      EXPECT_EQ("bar", item2.value_);
      EXPECT_EQ(SR_STRING_T, item2.type_);
      EXPECT_FALSE(item2.settable_);
  
      // Equality.
      EXPECT_TRUE(item1 == item2);
      EXPECT_TRUE(item2 == item1);
      EXPECT_FALSE(item1 != item2);
      EXPECT_FALSE(item2 != item1);
      EXPECT_EQ(item1, item2);
      EXPECT_EQ(item2, item1);
  }
  
  // Test get with test module.
  TEST(YangReprTest, getTest) {
  
      // Get a translator object to play with.
      S_Connection conn(new Connection("utils unittests"));
      S_Session sess(new Session(conn, SR_DS_CANDIDATE));
  
      // Fill the test module.
      string xpath;
      S_Val s_val;
  
      // Create a list.
      xpath = "/keatest-module:container/list";
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/string";
      s_val.reset(new Val("str", SR_STRING_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/boolean";
      s_val.reset(new Val(true, SR_BOOL_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/ui8";
      uint8_t u8(8);
      s_val.reset(new Val(u8, SR_UINT8_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/ui16";
      uint16_t u16(16);
      s_val.reset(new Val(u16, SR_UINT16_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/ui32";
      uint32_t u32(32);
      s_val.reset(new Val(u32, SR_UINT32_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/i8";
      int8_t s8(8);
      s_val.reset(new Val(s8, SR_INT8_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/i16";
      int16_t s16(16);
      s_val.reset(new Val(s16, SR_INT16_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/i32";
      int32_t s32(32);
      s_val.reset(new Val(s32, SR_INT32_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/id_ref";
      s_val.reset(new Val("keatest-module:id_1", SR_IDENTITYREF_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      xpath = "/keatest-module:main/enum";
      s_val.reset(new Val("maybe", SR_ENUM_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      // Binary.
      xpath = "/keatest-module:main/raw";
      s_val.reset(new Val("Zm9vYmFy", SR_BINARY_T));
      EXPECT_NO_THROW(sess->set_item(xpath.c_str(), s_val));
  
      // Get it.
      YangRepr repr(testModel);
      YRTree tree;
      EXPECT_NO_THROW(tree = repr.get(sess));
  
      // Verify.
      EXPECT_TRUE(repr.verify(testTree, sess, cerr));
  }
  
  // This test verifies that errors are handled properly.
  TEST(YangReprTrest, getTestErrors) {
      // Get a translator object to play with.
      S_Connection conn(new Connection("utils unittests"));
      S_Session sess(new Session(conn, SR_DS_CANDIDATE));
  
      // Get it.
      YangRepr repr(testModel);
      YRTree tree;
      EXPECT_NO_THROW(repr.set(testTree, sess));
  
      // Verify.
      EXPECT_TRUE(repr.verify(testTree, sess, cerr));
  
      // Some error messages will be displayed.
      cout << "Some error messages will be displayed. Please ignore." << endl;
  
      // Change a path.
      YRTree badpath = testTree;
      badpath[14].xpath_ = "/keatest-module:kernel-module"; // removed final 's'
      EXPECT_FALSE(repr.verify(badpath, sess, cerr));
  
      // Change a value.
      YRTree badvalue = testTree;
      badvalue[3].value_ = "Str"; // was "str"
      EXPECT_FALSE(repr.verify(badvalue, sess, cerr));
  
      // Change a type.
      YRTree badtype = testTree;
      badtype[10].type_ = SR_UINT32_T; // was SR_INT32_T
      EXPECT_FALSE(repr.verify(badtype, sess, cerr));
  
      // Add a record at the end.
      YRTree badmissing = testTree;
      const string& xpathpc = "/keatest-module:presence-container";
      badmissing.push_back(YRItem(xpathpc, "", SR_CONTAINER_PRESENCE_T, false));
      EXPECT_FALSE(repr.verify(badmissing, sess, cerr));
  
      // Delete last record.
      YRTree badextra = testTree;
      badextra.pop_back();
      EXPECT_FALSE(repr.verify(badextra, sess, cerr));
  }
  
  // Test set with test module.
  TEST(YangReprTest, setTest) {
      // Get a translator object to play with.
      S_Connection conn(new Connection("utils unittests"));
      S_Session sess(new Session(conn, SR_DS_CANDIDATE));
  
      // Set the module content.
      YangRepr repr(testModel);
      EXPECT_NO_THROW(repr.set(testTree, sess));
  
      // Verify it.
      EXPECT_TRUE(repr.verify(testTree, sess, cerr));
  }
  
  /// @brief Tests specified configuration.
  ///
  /// Configuration is set and then verified using YangRepr object.
  ///
  /// @param model name of the model to be verified against.
  /// @param tree tree to be verified.
  void sanityCheckConfig(const std::string& model, const YRTree& tree) {
      // Get a translator object to play with.
      S_Connection conn(new Connection("utils unittests"));
      S_Session sess(new Session(conn, SR_DS_CANDIDATE));
  
      // Get it.
      YangRepr repr(model);
  
      EXPECT_NO_THROW(repr.set(tree, sess))
          << " for model " << model;
      bool result = false;
      EXPECT_NO_THROW(result = repr.verify(tree, sess, cerr))
          << " for model " << model;
      EXPECT_TRUE(result);
  }
  
  // This is test environment sanity check. It verifies that all configuration
  // defined in yang_configs.h are sane.
  TEST(YangReprTest, verifyConfigs) {
      for (auto x : test_configs) {
          sanityCheckConfig(x.first, x.second);
      }
  }
  
  }; // end of anonymous namespace
  