name: Make 'at' method to check if requested components is in bounds

Change-Id: I28744a694e1ead48892bb3cfe918b7132b769a5a
diff --git a/src/name.hpp b/src/name.hpp
index 96d43c0..6d7582f 100644
--- a/src/name.hpp
+++ b/src/name.hpp
@@ -346,10 +346,21 @@
   {
     return get(i);
   }
-  
+
+  /**
+   * @brief Get component at the specified index
+   *
+   * Unlike get() and operator[] methods, at() checks for out of bounds
+   * and will throw Name::Error when it happens
+   *
+   * @throws Name::Error if index out of bounds
+   */
   const Component&
   at(ssize_t i) const
   {
+    if ((i >= 0 && i >= size()) || (i < 0 && i < -size()))
+      throw Error("Requested component does not exist (out of bounds)");
+
     return get(i);
   }
 
diff --git a/tests/test-name.cpp b/tests/test-name.cpp
index 236f8b1..b80e37e 100644
--- a/tests/test-name.cpp
+++ b/tests/test-name.cpp
@@ -32,7 +32,20 @@
                              0x6e,  0x64,  0x6e};
 
 
-BOOST_AUTO_TEST_CASE (Encode)
+BOOST_AUTO_TEST_CASE(Basic)
+{
+  Name name("/hello/world");
+
+  BOOST_CHECK_NO_THROW(name.at(0));
+  BOOST_CHECK_NO_THROW(name.at(1));
+  BOOST_CHECK_NO_THROW(name.at(-1));
+  BOOST_CHECK_NO_THROW(name.at(-2));
+
+  BOOST_CHECK_THROW(name.at(2), Name::Error);
+  BOOST_CHECK_THROW(name.at(-3), Name::Error);
+}
+
+BOOST_AUTO_TEST_CASE(Encode)
 {
   Name name("/local/ndn/prefix");
 
@@ -57,7 +70,7 @@
 }
 
 
-BOOST_AUTO_TEST_CASE (Decode)
+BOOST_AUTO_TEST_CASE(Decode)
 {
   Block block(TestName, sizeof(TestName));
 
@@ -66,7 +79,7 @@
   BOOST_CHECK_EQUAL(name.toUri(), "/local/ndn/prefix");
 }
 
-BOOST_AUTO_TEST_CASE (AppendsAndMultiEncode)
+BOOST_AUTO_TEST_CASE(AppendsAndMultiEncode)
 {
   Name name("/local");