diff --git a/deps/RTKLIB b/deps/RTKLIB
index b8d52b91639ef1ed3a8c676c43457164865a9df3..5f9fc9b46abc503ab95b4b0ea10f3385d7560404 160000
--- a/deps/RTKLIB
+++ b/deps/RTKLIB
@@ -1 +1 @@
-Subproject commit b8d52b91639ef1ed3a8c676c43457164865a9df3
+Subproject commit 5f9fc9b46abc503ab95b4b0ea10f3385d7560404
diff --git a/include/gnss_utils/navigation.h b/include/gnss_utils/navigation.h
index 861742e8b8bd7ef35319c072a84cece982d7e27a..f47a7bc0617c1250f2a99233c83d67e58f81f048 100644
--- a/include/gnss_utils/navigation.h
+++ b/include/gnss_utils/navigation.h
@@ -2,6 +2,7 @@
 #define INCLUDE_GNSS_UTILS_NAVIGATION_H_
 
 #include "gnss_utils/gnss_utils.h"
+#include "gnss_utils/utils/utils.h"
 
 namespace GnssUtils
 {
@@ -58,12 +59,6 @@ public:
   void print();
 
   //////////////////////////////// nav UTILS //////////////////////////////////////
-  template <typename T>
-  static bool addToArray(const T& new_element, T*& array, int& n, int& nmax);
-  template <typename T>
-  static bool copyArray(const T* array_in, const int& n_in, T*& array_out, int& n_out, int& nmax_out);
-  template <typename T>
-  static void freeArray(T*& array, int& n, int& nmax);
   static void freeEph(nav_t& nav);
   static void freeGeph(nav_t& nav);
   static void freeSeph(nav_t& nav);
@@ -238,67 +233,6 @@ inline void Navigation::freeAlmanac()
 }
 
 //////////////////////////////// nav UTILS //////////////////////////////////////
-template <typename T>
-inline bool Navigation::addToArray(const T& new_element, T*& array, int& n, int& nmax)
-{
-  // std::cout << "addToArray: n = " << n << " nmax = " << nmax << "\n";
-  // "inspired" from RTKLIB rinex.c
-  T* array_ref;
-  if (nmax <= n)
-  {
-    // std::cout << "addToArray: nmax <= n\n";
-    nmax += 1024;
-    if (!(array_ref = (T*)realloc(array, sizeof(T) * nmax)))
-    {
-      printf("addToArray malloc error: n=%d\n", nmax);
-      free(array);
-      array = NULL;
-      n = nmax = 0;
-      return false;
-    }
-    // std::cout << "addToArray: assigning reallocated array\n";
-    array = array_ref;
-  }
-  // std::cout << "addToArray: adding element " << n << "\n";
-  array[n++] = new_element;
-  // std::cout << "addToArray: added!\n";
-  return true;
-}
-
-template <typename T>
-inline bool Navigation::copyArray(const T* array_in, const int& n_in, T*& array_out, int& n_out, int& nmax_out)
-{
-  // std::cout << "copyArray: " << n_in << " elements\n";
-  if (array_in == NULL)
-    return false;
-
-  // std::cout << "copyArray: array in not null\n";
-
-  for (int i = 0; i < n_in; i++)
-  {
-    // std::cout << "copyArray: adding element " << i << "\n";
-    if (!addToArray<T>(array_in[i], array_out, n_out, nmax_out))
-    {
-      // std::cout << "copyArray: failed to add..\n";
-      return false;
-    }
-    // std::cout << "copyArray: n_out = " << n_out << " nmax_out = " << nmax_out << "\n";
-  }
-
-  // std::cout << "copyArray: all copied\n";
-
-  return true;
-}
-
-template <typename T>
-void Navigation::freeArray(T*& array, int& n, int& nmax)
-{
-  if (array != NULL)
-    free(array);
-  array = NULL;
-  n = nmax = 0;
-}
-
 inline void Navigation::freeEph(nav_t& nav)
 {
   freeArray<eph_t>(nav.eph, nav.n, nav.nmax);
diff --git a/include/gnss_utils/observations.h b/include/gnss_utils/observations.h
index 0a94fbc1cbade6707d0e871d71a4a4ce6126f13a..cd6bea585de5766dc43bf2f912e2000f635efc84 100644
--- a/include/gnss_utils/observations.h
+++ b/include/gnss_utils/observations.h
@@ -14,12 +14,6 @@ public:
   Observations(const Observations& obs);
   ~Observations();
 
-  // Public objects
-
-  // Public methods
-
-  /* - Observations -  */
-
   void clearObservations();
 
   void addObservation(const obsd_t& obs);
@@ -45,7 +39,7 @@ public:
 
   bool hasSatellite(const unsigned char& i) const;
 
-  void print(obsd_t& _obs);
+  static void print(obsd_t& _obs);
   void printBySat(const int& _sat);
   void printByIdx(const int& _idx);
   void print();
@@ -151,4 +145,4 @@ inline bool Observations::operator !=(const Observations &other_obs) const
 }
 
 }  // namespace GnssUtils
-#endif // INCLUDE_GNSS_UTILS_OBSERVATIONS_H_
+#endif  // INCLUDE_GNSS_UTILS_OBSERVATIONS_H_
diff --git a/include/gnss_utils/utils/utils.h b/include/gnss_utils/utils/utils.h
index ad1c627f68272fd3aa425e0028c99cdba8354b1b..06eba1b1861a2b9a82ee7272fc7743f7810a234c 100644
--- a/include/gnss_utils/utils/utils.h
+++ b/include/gnss_utils/utils/utils.h
@@ -10,6 +10,8 @@
 #include "gnss_utils/gnss_utils.h"
 
 #define ARRAY_SIZE(arr) sizeof(arr) / sizeof(arr[0])
+#define ARRAY2D_NROWS(arr) sizeof(arr) / sizeof(arr[0])
+#define ARRAY2D_NCOLS(arr) sizeof(arr[0]) / sizeof(arr[0][0])
 #define GNSSUTILS_MSG "--GnssUtils--"
 
 namespace GnssUtils
@@ -21,27 +23,176 @@ void printArray(std::string _name, double* _array, int size);
 void printArray(std::string _name, float* _array, int size);
 
 template <typename T>
-bool equalArray(const T* array1, const T* array2, const int& size1, const int& size2)
+inline bool addToArray(const T& new_element, T*& array, int& n, int& nmax)
 {
-  if (size1 != size2)
+  // std::cout << "addToArray: n = " << n << " nmax = " << nmax << "\n";
+  // "inspired" from RTKLIB rinex.c
+  T* array_ref;
+  if (nmax <= n)
+  {
+    // std::cout << "addToArray: nmax <= n\n";
+    nmax += 1024;
+    if (!(array_ref = (T*)realloc(array, sizeof(T) * nmax)))
+    {
+      printf("addToArray malloc error: n=%d\n", nmax);
+      free(array);
+      array = NULL;
+      n = nmax = 0;
+      return false;
+    }
+    // std::cout << "addToArray: assigning reallocated array\n";
+    array = array_ref;
+  }
+  // std::cout << "addToArray: adding element " << n << "\n";
+  array[n++] = new_element;
+  // std::cout << "addToArray: added!\n";
+  return true;
+}
+
+template <typename T>
+inline bool copyArray(const T* array_in, const int& n_in, T*& array_out, int& n_out, int& nmax_out)
+{
+  // std::cout << "copyArray: " << n_in << " elements\n";
+  if (array_in == NULL)
+    return false;
+
+  // std::cout << "copyArray: array in not null\n";
+
+  for (int i = 0; i < n_in; i++)
+  {
+    // std::cout << "copyArray: adding element " << i << "\n";
+    if (!addToArray<T>(array_in[i], array_out, n_out, nmax_out))
+    {
+      // std::cout << "copyArray: failed to add..\n";
+      return false;
+    }
+    // std::cout << "copyArray: n_out = " << n_out << " nmax_out = " << nmax_out << "\n";
+  }
+
+  // std::cout << "copyArray: all copied\n";
+
+  return true;
+}
+
+template <typename T>
+void freeArray(T*& array, int& n, int& nmax)
+{
+  if (array != NULL)
+    free(array);
+  array = NULL;
+  n = nmax = 0;
+}
+
+template <typename T>
+bool equalArray(const T* array_1, const T* array_2, const int& n1, const int& n2)
+{
+  if (n1 != n2)
     return false;
 
-  for (int ii = 0; ii < size1; ++ii)
+  for (int i = 0; i < n1; ++i)
   {
-    if (array1[ii] != array2[ii])
+    if (array_1[i] != array_2[i])
       return false;
   }
 
   return true;
 }
 
+template <typename T>
+bool equalArray2d(const T*   array_1,
+                  const T*   array_2,
+                  const int& nrow_1,
+                  const int& ncol_1,
+                  const int& nrow_2,
+                  const int& ncol_2)
+{
+  if (nrow_1 != nrow_2)
+    return false;
+  if (ncol_1 != ncol_2)
+    return false;
+
+  for (int i = 0; i < nrow_1; ++i)
+  {
+    for (int j = 0; j < ncol_1; ++j)
+    {
+      if (*(array_1 + i * ncol_1 + j) != *(array_2 + i * ncol_1 + j))
+        return false;
+    }
+  }
+
+  return true;
+}
+
+template <typename T>
+bool equalArray3d(const T*   array_1,
+                  const T*   array_2,
+                  const int& nmat_1,
+                  const int& nrow_1,
+                  const int& ncol_1,
+                  const int& nmat_2,
+                  const int& nrow_2,
+                  const int& ncol_2)
+{
+  if (nmat_1 != nmat_2)
+    return false;
+  if (nrow_1 != nrow_2)
+    return false;
+  if (ncol_1 != ncol_2)
+    return false;
+
+  for (int i = 0; i < nmat_1; ++i)
+  {
+    for (int j = 0; j < nrow_1; ++j)
+    {
+      for (int k = 0; k < ncol_1; ++k)
+      {
+        if (*(array_1 + i * ncol_1 * nrow_1 + j * ncol_1 + k) != *(array_2 + i * ncol_1 * nrow_1 + j * ncol_1 + k))
+          return false;
+      }
+    }
+  }
+
+  return true;
+}
+
 }  // namespace GnssUtils
 
 bool operator==(const gtime_t& time1, const gtime_t& time2);
 bool operator!=(const gtime_t& time1, const gtime_t& time2);
+
 bool operator==(const obsd_t& obs1, const obsd_t& obs2);
 bool operator!=(const obsd_t& obs1, const obsd_t& obs2);
 bool operator==(const obs_t& obs1, const obs_t& obs2);
 bool operator!=(const obs_t& obs1, const obs_t& obs2);
 
+bool operator==(const eph_t& eph1, const eph_t& eph2);
+bool operator!=(const eph_t& eph1, const eph_t& eph2);
+
+bool operator==(const geph_t& geph1, const geph_t& geph2);
+bool operator!=(const geph_t& geph1, const geph_t& geph2);
+
+bool operator==(const seph_t& seph1, const seph_t& seph2);
+bool operator!=(const seph_t& seph1, const seph_t& seph2);
+
+bool operator==(const peph_t& peph1, const peph_t& peph2);
+bool operator!=(const peph_t& peph1, const peph_t& peph2);
+
+bool operator==(const pclk_t& pclk1, const pclk_t& pclk2);
+bool operator!=(const pclk_t& pclk1, const pclk_t& pclk2);
+
+bool operator==(const alm_t& alm1, const alm_t& alm2);
+bool operator!=(const alm_t& alm1, const alm_t& alm2);
+
+bool operator==(const tec_t& tec1, const tec_t& tec2);
+bool operator!=(const tec_t& tec1, const tec_t& tec2);
+
+bool operator==(const fcbd_t& fcbd1, const fcbd_t& fcbd2);
+bool operator!=(const fcbd_t& fcbd1, const fcbd_t& fcbd2);
+
+bool operator==(const erp_t& erp1, const erp_t& erp2);
+bool operator!=(const erp_t& erp1, const erp_t& erp2);
+
+bool operator==(const nav_t& nav1, const nav_t& nav2);
+bool operator!=(const nav_t& nav1, const nav_t& nav2);
+
 #endif  // INCLUDE_GNSS_UTILS_UTILS_UTILS_H_
diff --git a/src/examples/gnss_utils_test.cpp b/src/examples/gnss_utils_test.cpp
index 1a59e2d85c7b3b41404f808283866c07703ec8a1..fba3b7f10045cd17d2238b30834b8f0c8f53e6f6 100644
--- a/src/examples/gnss_utils_test.cpp
+++ b/src/examples/gnss_utils_test.cpp
@@ -32,21 +32,23 @@ int main(int argc, char* argv[])
   double      dt  = 0.0;        // no limit
   const char* opt = "";         // only GPS | GPS+GAL: "-SYS=G,L" | ALL: ""
 
-  // RTKLIB trace
-  // char str_file[80];
-  // snprintf(str_file, sizeof str_file, "../src/examples/trace");
-
   // load observations from RINEX file
   observations.loadFromRinex("../src/examples/sample_data.obs", t_start, t_end, dt, opt);
   observations.print();
 
-  // Trace close
-  // traceclose();
+  // RTKLIB trace
+  // char str_file[80];
+  // snprintf(str_file, sizeof str_file, "../src/examples/trace");
+  // tracelevel(5);
+  // traceopen(str_file);
 
   // load navigation from RINEX file
   navigation.loadFromRinex("../src/examples/sample_data.nav", t_start, t_end, dt, opt);
   navigation.print();
 
+  // Trace close
+  // traceclose();
+
   /* Set processing options */
 
   /* header */
diff --git a/src/examples/trace b/src/examples/trace
new file mode 100644
index 0000000000000000000000000000000000000000..362c7af58c323df3a6d40b9e316a4b74679ddb30
--- /dev/null
+++ b/src/examples/trace
@@ -0,0 +1,86 @@
+3 readrnxt: file=../src/examples/sample_data.nav rcv=1
+3 expath  : path=../src/examples/sample_data.nav nmax=1024
+3 expath  : file=../src/examples/sample_data.nav
+3 readrnxfile: file=../src/examples/sample_data.nav flag=0 index=1
+3 rtk_uncompress: file=../src/examples/sample_data.nav
+3 rtk_uncompress: stat=0
+3 readrnxfp: flag=0 index=1
+3 readrnxh:
+4 decode_navh:
+4 decode_navh:
+4 decode_navh:
+4 decode_navh:
+4 decode_navh:
+4 decode_navh:
+4 decode_navh:
+4 decode_navh:
+3 readrnxnav: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 decode_seph: ver=3.04 sat=49
+4 readrnxnavb: ver=3.04 sys=0
+4 decode_seph: ver=3.04 sat=38
+4 readrnxnavb: ver=3.04 sys=0
+4 decode_seph: ver=3.04 sat=36
+4 readrnxnavb: ver=3.04 sys=0
+4 decode_seph: ver=3.04 sat=49
+4 readrnxnavb: ver=3.04 sys=0
+4 decode_seph: ver=3.04 sat=36
+4 readrnxnavb: ver=3.04 sys=0
+4 decode_seph: ver=3.04 sat=36
+4 readrnxnavb: ver=3.04 sys=0
+4 decode_seph: ver=3.04 sat=49
+4 readrnxnavb: ver=3.04 sys=0
+4 decode_seph: ver=3.04 sat=49
+4 readrnxnavb: ver=3.04 sys=0
+4 decode_seph: ver=3.04 sat=36
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+4 readrnxnavb: ver=3.04 sys=0
+3 uniqnav: neph=0 ngeph=0 nseph=9
+3 uniqeph: n=0
+3 uniqgeph: ng=0
+3 uniqseph: ns=9
+4 uniqseph: ns=9
diff --git a/src/navigation.cpp b/src/navigation.cpp
index 66b861b71dc5587eb3bbb80b2dee0f43084ad40b..e71bbce021ceac1064d11e879d2523818d672a70 100644
--- a/src/navigation.cpp
+++ b/src/navigation.cpp
@@ -5,32 +5,44 @@ using namespace GnssUtils;
 Navigation::Navigation()
 {
   // array initialization
-  nav_.n = nav_.nmax = nav_.ng = nav_.ngmax = nav_.ns = nav_.nsmax = nav_.ne = nav_.nemax = nav_.nc = nav_.ncmax =
-      nav_.na = nav_.namax = nav_.nt = nav_.ntmax = nav_.nf = nav_.nfmax = 0;
-  nav_.eph                                                               = NULL;
-  nav_.geph                                                              = NULL;
-  nav_.seph                                                              = NULL;
-  nav_.peph                                                              = NULL;
-  nav_.pclk                                                              = NULL;
-  nav_.alm                                                               = NULL;
-  nav_.tec                                                               = NULL;
-  nav_.fcb                                                               = NULL;
+  nav_.n = nav_.nmax = 0;
+  nav_.ng = nav_.ngmax = 0;
+  nav_.ns = nav_.nsmax = 0;
+  nav_.ne = nav_.nemax = 0;
+  nav_.nc = nav_.ncmax = 0;
+  nav_.na = nav_.namax = 0;
+  nav_.nt = nav_.ntmax = 0;
+  nav_.nf = nav_.nfmax = 0;
+  nav_.eph             = NULL;
+  nav_.geph            = NULL;
+  nav_.seph            = NULL;
+  nav_.peph            = NULL;
+  nav_.pclk            = NULL;
+  nav_.alm             = NULL;
+  nav_.tec             = NULL;
+  nav_.fcb             = NULL;
   clearNavigation();
 }
 
 Navigation::Navigation(const Navigation& nav)
 {
   // array initialization
-  nav_.n = nav_.nmax = nav_.ng = nav_.ngmax = nav_.ns = nav_.nsmax = nav_.ne = nav_.nemax = nav_.nc = nav_.ncmax =
-      nav_.na = nav_.namax = nav_.nt = nav_.ntmax = nav_.nf = nav_.nfmax = 0;
-  nav_.eph                                                               = NULL;
-  nav_.geph                                                              = NULL;
-  nav_.seph                                                              = NULL;
-  nav_.peph                                                              = NULL;
-  nav_.pclk                                                              = NULL;
-  nav_.alm                                                               = NULL;
-  nav_.tec                                                               = NULL;
-  nav_.fcb                                                               = NULL;
+  nav_.n = nav_.nmax = 0;
+  nav_.ng = nav_.ngmax = 0;
+  nav_.ns = nav_.nsmax = 0;
+  nav_.ne = nav_.nemax = 0;
+  nav_.nc = nav_.ncmax = 0;
+  nav_.na = nav_.namax = 0;
+  nav_.nt = nav_.ntmax = 0;
+  nav_.nf = nav_.nfmax = 0;
+  nav_.eph             = NULL;
+  nav_.geph            = NULL;
+  nav_.seph            = NULL;
+  nav_.peph            = NULL;
+  nav_.pclk            = NULL;
+  nav_.alm             = NULL;
+  nav_.tec             = NULL;
+  nav_.fcb             = NULL;
   clearNavigation();
   setNavigation(nav.getNavigation());
 }
@@ -130,7 +142,8 @@ void Navigation::loadFromRinex(const std::string& rnx_file, gtime_t t_start, gti
     uniqueNavigation();
   }
   else
-    std::cout << "Navigation: couldn't load provided observation file, reason: " << (stat == 0 ? "no data" : "error") << std::endl;
+    std::cout << "Navigation: couldn't load provided observation file, reason: " << (stat == 0 ? "no data" : "error")
+              << std::endl;
 }
 
 void Navigation::copyAllArrays(const nav_t& nav)
diff --git a/src/observations.cpp b/src/observations.cpp
index 2cedfe367af1266e0b6bf8651c9b6b889dedb374..956c13f5b8b07b954f6e34a6ab0e84a3e158e63e 100644
--- a/src/observations.cpp
+++ b/src/observations.cpp
@@ -157,14 +157,18 @@ void Observations::removeObservationBySat(const int& _sat)
   assert(sat_2_idx_.size() == obs_.size());
 }
 
-void Observations::print(obsd_t& _obs)
+static void Observations::print(obsd_t& _obs)
 {
   std::string msg = "Observation of satellite #" + std::to_string(_obs.sat);
   GnssUtils::print(msg);
   std::cout << "Time [s]: " << _obs.time.time << " + " << _obs.time.sec << "\n";
+  std::cout << "Time valid: " << _obs.timevalid << std::endl;
   printArray("SNR: ", _obs.SNR, ARRAY_SIZE(_obs.SNR));
   printArray("LLI: ", _obs.LLI, ARRAY_SIZE(_obs.LLI));
   printArray("code: ", _obs.code, ARRAY_SIZE(_obs.code));
+  printArray("code: ", _obs.qualL, ARRAY_SIZE(_obs.qualL));
+  printArray("code: ", _obs.qualP, ARRAY_SIZE(_obs.qualP));
+  printf("Freq. channel: %uc \n", _obs.freq);
   printArray("L: ", _obs.L, ARRAY_SIZE(_obs.L));
   printArray("P: ", _obs.P, ARRAY_SIZE(_obs.P));
   printArray("D: ", _obs.D, ARRAY_SIZE(_obs.D));
diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp
index 8e7c1225b63ee88fbda04b94ff78cc1a222f776d..49a7f38dcc83cf51ce95897a1d0ba89a29918d27 100644
--- a/src/utils/utils.cpp
+++ b/src/utils/utils.cpp
@@ -67,47 +67,333 @@ bool operator==(const gtime_t& time1, const gtime_t& time2)
 {
   return (difftime(time1.time, time2.time) == 0.0 && time1.sec == time2.sec);
 }
-
 bool operator!=(const gtime_t& time1, const gtime_t& time2)
 {
-  return not (time1 == time2);
+  return not(time1 == time2);
 }
 
 bool operator==(const obsd_t& obs1, const obsd_t& obs2)
 {
-  return obs1.time == obs2.time &&
-         obs1.eventime == obs2.eventime &&
-         obs1.timevalid == obs2.timevalid &&
-         obs1.sat == obs2.sat &&
-         obs1.rcv == obs2.rcv &&
-         memcmp(obs1.SNR, obs2.SNR, sizeof(obs1.SNR)) == 0 &&
-         memcmp(obs1.LLI, obs2.LLI, sizeof(obs1.LLI)) == 0 &&
-         memcmp(obs1.code, obs2.code, sizeof(obs1.code)) == 0 &&
-         memcmp(obs1.qualL, obs2.qualL, sizeof(obs1.qualL)) == 0 &&
-         memcmp(obs1.qualP, obs2.qualP, sizeof(obs1.qualP)) == 0 &&
+  return obs1.time == obs2.time && obs1.eventime == obs2.eventime && obs1.timevalid == obs2.timevalid &&
+         obs1.sat == obs2.sat && obs1.rcv == obs2.rcv &&
+         GnssUtils::equalArray<unsigned char>(obs1.SNR, obs2.SNR, ARRAY_SIZE(obs1.SNR), ARRAY_SIZE(obs2.SNR)) &&
+         GnssUtils::equalArray<unsigned char>(obs1.LLI, obs2.LLI, ARRAY_SIZE(obs1.LLI), ARRAY_SIZE(obs2.LLI)) &&
+         GnssUtils::equalArray<unsigned char>(obs1.code, obs2.code, ARRAY_SIZE(obs1.code), ARRAY_SIZE(obs2.code)) &&
+         GnssUtils::equalArray<unsigned char>(obs1.qualL, obs2.qualL, ARRAY_SIZE(obs1.qualL), ARRAY_SIZE(obs2.qualL)) &&
+         GnssUtils::equalArray<unsigned char>(obs1.qualP, obs2.qualP, ARRAY_SIZE(obs1.qualP), ARRAY_SIZE(obs2.qualP)) &&
          obs1.freq == obs2.freq &&
-         GnssUtils::equalArray<double>(obs1.L, obs2.L, sizeof(obs1.L) / sizeof(obs1.L[0]), sizeof(obs2.L) / sizeof(obs2.L[0])) &&
-         GnssUtils::equalArray<double>(obs1.P, obs2.P, sizeof(obs1.P) / sizeof(obs1.P[0]), sizeof(obs2.P) / sizeof(obs2.P[0])) &&
-         GnssUtils::equalArray<float>(obs1.D, obs2.D, sizeof(obs1.D) / sizeof(obs1.D[0]), sizeof(obs2.D) / sizeof(obs2.D[0]));
+         GnssUtils::equalArray<double>(obs1.L, obs2.L, ARRAY_SIZE(obs1.L), ARRAY_SIZE(obs2.L)) &&
+         GnssUtils::equalArray<double>(obs1.P, obs2.P, ARRAY_SIZE(obs1.P), ARRAY_SIZE(obs2.P)) &&
+         GnssUtils::equalArray<float>(obs1.D, obs2.D, ARRAY_SIZE(obs1.D), ARRAY_SIZE(obs2.D));
 }
-
 bool operator!=(const obsd_t& obs1, const obsd_t& obs2)
 {
-  return not (obs1 == obs2);
+  return not(obs1 == obs2);
 }
 
 bool operator==(const obs_t& obs1, const obs_t& obs2)
 {
-    return obs1.n == obs2.n &&
-           obs1.nmax == obs2.nmax &&
-           obs1.flag == obs2.flag &&
-           obs1.rcvcount == obs2.rcvcount &&
-           obs1.tmcount == obs2.tmcount &&
-           *(obs1.data) == *(obs2.data);
-}
+  if (obs1.n != obs2.n)
+    return false;
+  for (int i = 0; i < obs1.n; ++i)
+  {
+    if (obs1.data[i] != obs2.data[i])
+      return false;
+  }
 
+  return obs1.nmax == obs2.nmax && obs1.flag == obs2.flag && obs1.rcvcount == obs2.rcvcount &&
+         obs1.tmcount == obs2.tmcount;
+}
 bool operator!=(const obs_t& obs1, const obs_t& obs2)
 {
-  return not (obs1 == obs2);
+  return not(obs1 == obs2);
+}
+
+bool operator==(const eph_t& eph1, const eph_t& eph2)
+{
+  return eph1.sat == eph2.sat && eph1.iode == eph2.iode && eph1.iodc == eph2.iodc && eph1.sva == eph2.sva &&
+         eph1.svh == eph2.svh && eph1.week == eph2.week && eph1.code == eph2.code && eph1.flag == eph2.flag &&
+         eph1.toe == eph2.toe && eph1.toc == eph2.toc && eph1.ttr == eph2.ttr && eph1.A == eph2.A && eph1.e == eph2.e &&
+         eph1.i0 == eph2.i0 && eph1.OMG0 == eph2.OMG0 && eph1.omg == eph2.omg && eph1.M0 == eph2.M0 &&
+         eph1.deln == eph2.deln && eph1.OMGd == eph2.OMGd && eph1.idot == eph2.idot && eph1.crc == eph2.crc &&
+         eph1.crs == eph2.crs && eph1.cuc == eph2.cuc && eph1.cus == eph2.cus && eph1.cic == eph2.cic &&
+         eph1.cis == eph2.cis && eph1.toes == eph2.toes && eph1.fit == eph2.fit && eph1.f0 == eph2.f0 &&
+         eph1.f1 == eph2.f1 && eph1.f2 == eph2.f2 &&
+         GnssUtils::equalArray<double>(eph1.tgd, eph2.tgd, ARRAY_SIZE(eph1.tgd), ARRAY_SIZE(eph2.tgd)) &&
+         eph1.Adot == eph2.Adot && eph1.ndot == eph2.ndot;
+}
+bool operator!=(const eph_t& eph1, const eph_t& eph2)
+{
+  return not(eph1 == eph2);
+}
+
+bool operator==(const geph_t& geph1, const geph_t& geph2)
+{
+  return geph1.sat == geph2.sat && geph1.iode == geph2.iode && geph1.frq == geph2.frq && geph1.svh == geph2.svh &&
+         geph1.sva == geph2.sva && geph1.age == geph2.age && geph1.toe == geph2.toe && geph1.tof == geph2.tof &&
+         GnssUtils::equalArray<double>(geph1.pos, geph2.pos, ARRAY_SIZE(geph1.pos), ARRAY_SIZE(geph2.pos)) &&
+         GnssUtils::equalArray<double>(geph1.vel, geph2.vel, ARRAY_SIZE(geph1.vel), ARRAY_SIZE(geph2.vel)) &&
+         GnssUtils::equalArray<double>(geph1.acc, geph2.acc, ARRAY_SIZE(geph1.acc), ARRAY_SIZE(geph2.acc)) &&
+         geph1.taun == geph2.taun && geph1.gamn == geph2.gamn && geph1.dtaun == geph2.dtaun;
+}
+bool operator!=(const geph_t& geph1, const geph_t& geph2)
+{
+  return not(geph1 == geph2);
+}
+
+bool operator==(const seph_t& seph1, const seph_t& seph2)
+{
+  return seph1.sat == seph2.sat && seph1.t0 == seph2.t0 && seph1.tof == seph2.tof && seph1.sva == seph2.sva &&
+         seph1.svh == seph2.svh &&
+         GnssUtils::equalArray<double>(seph1.pos, seph2.pos, ARRAY_SIZE(seph1.pos), ARRAY_SIZE(seph2.pos)) &&
+         GnssUtils::equalArray<double>(seph1.vel, seph2.vel, ARRAY_SIZE(seph1.vel), ARRAY_SIZE(seph2.vel)) &&
+         GnssUtils::equalArray<double>(seph1.acc, seph2.acc, ARRAY_SIZE(seph1.acc), ARRAY_SIZE(seph2.acc)) &&
+         seph1.af0 == seph2.af0 && seph1.af1 == seph2.af1;
+}
+bool operator!=(const seph_t& seph1, const seph_t& seph2)
+{
+  return not(seph1 == seph2);
+}
+
+bool operator==(const peph_t& peph1, const peph_t& peph2)
+{
+  return peph1.time == peph2.time && peph1.index == peph2.index &&
+         GnssUtils::equalArray2d<double>(&peph1.pos[0][0],
+                                         &peph2.pos[0][0],
+                                         ARRAY2D_NROWS(peph1.pos),
+                                         ARRAY2D_NCOLS(peph1.pos),
+                                         ARRAY2D_NROWS(peph2.pos),
+                                         ARRAY2D_NCOLS(peph2.pos)) &&
+         GnssUtils::equalArray2d<float>(&peph1.std[0][0],
+                                        &peph2.std[0][0],
+                                        ARRAY2D_NROWS(peph1.std),
+                                        ARRAY2D_NCOLS(peph1.std),
+                                        ARRAY2D_NROWS(peph2.std),
+                                        ARRAY2D_NCOLS(peph2.std)) &&
+         GnssUtils::equalArray2d<double>(&peph1.vel[0][0],
+                                         &peph2.vel[0][0],
+                                         ARRAY2D_NROWS(peph1.vel),
+                                         ARRAY2D_NCOLS(peph1.vel),
+                                         ARRAY2D_NROWS(peph2.vel),
+                                         ARRAY2D_NCOLS(peph2.vel)) &&
+         GnssUtils::equalArray2d<float>(&peph1.vst[0][0],
+                                        &peph2.vst[0][0],
+                                        ARRAY2D_NROWS(peph1.vst),
+                                        ARRAY2D_NCOLS(peph1.vst),
+                                        ARRAY2D_NROWS(peph2.vst),
+                                        ARRAY2D_NCOLS(peph2.vst)) &&
+         GnssUtils::equalArray2d<float>(&peph1.cov[0][0],
+                                        &peph2.cov[0][0],
+                                        ARRAY2D_NROWS(peph1.cov),
+                                        ARRAY2D_NCOLS(peph1.cov),
+                                        ARRAY2D_NROWS(peph2.cov),
+                                        ARRAY2D_NCOLS(peph2.cov)) &&
+         GnssUtils::equalArray2d<float>(&peph1.vco[0][0],
+                                        &peph2.vco[0][0],
+                                        ARRAY2D_NROWS(peph1.vco),
+                                        ARRAY2D_NCOLS(peph1.vco),
+                                        ARRAY2D_NROWS(peph2.vco),
+                                        ARRAY2D_NCOLS(peph2.vco));
+}
+bool operator!=(const peph_t& peph1, const peph_t& peph2)
+{
+  return not(peph1 == peph2);
+}
+
+bool operator==(const pclk_t& pclk1, const pclk_t& pclk2)
+{
+  return pclk1.time == pclk2.time && pclk1.index == pclk2.index &&
+         GnssUtils::equalArray2d<double>(&pclk1.clk[0][0],
+                                         &pclk2.clk[0][0],
+                                         ARRAY2D_NROWS(pclk1.clk),
+                                         ARRAY2D_NCOLS(pclk1.clk),
+                                         ARRAY2D_NROWS(pclk2.clk),
+                                         ARRAY2D_NCOLS(pclk2.clk)) &&
+         GnssUtils::equalArray2d<float>(&pclk1.std[0][0],
+                                        &pclk2.std[0][0],
+                                        ARRAY2D_NROWS(pclk1.std),
+                                        ARRAY2D_NCOLS(pclk1.std),
+                                        ARRAY2D_NROWS(pclk2.std),
+                                        ARRAY2D_NCOLS(pclk2.std));
+}
+bool operator!=(const pclk_t& pclk1, const pclk_t& pclk2)
+{
+  return not(pclk1 == pclk2);
+}
+
+bool operator==(const alm_t& alm1, const alm_t& alm2)
+{
+  return alm1.sat == alm2.sat && alm1.svh == alm2.svh && alm1.svconf == alm2.svconf && alm1.week == alm2.week &&
+         alm1.toa == alm2.toa && alm1.A == alm2.A && alm1.e == alm2.e && alm1.i0 == alm2.i0 && alm1.OMG0 == alm2.OMG0 &&
+         alm1.omg == alm2.omg && alm1.M0 == alm2.M0 && alm1.OMGd == alm2.OMGd && alm1.toas == alm2.toas &&
+         alm1.f0 == alm2.f0 && alm1.f1 == alm2.f1;
+}
+bool operator!=(const alm_t& alm1, const alm_t& alm2)
+{
+  return not(alm1 == alm2);
 }
 
+bool operator==(const tec_t& tec1, const tec_t& tec2)
+{
+  return tec1.time == tec2.time &&
+         GnssUtils::equalArray<int>(tec1.ndata, tec2.ndata, ARRAY_SIZE(tec1.ndata), ARRAY_SIZE(tec2.ndata)) &&
+         tec1.rb == tec2.rb &&
+         GnssUtils::equalArray<double>(tec1.lats, tec2.lats, ARRAY_SIZE(tec1.lats), ARRAY_SIZE(tec2.lats)) &&
+         GnssUtils::equalArray<double>(tec1.lons, tec2.lons, ARRAY_SIZE(tec1.lons), ARRAY_SIZE(tec2.lons)) &&
+         GnssUtils::equalArray<double>(tec1.hgts, tec2.hgts, ARRAY_SIZE(tec1.hgts), ARRAY_SIZE(tec2.hgts));
+  // TODO: *data and *rms
+}
+bool operator!=(const tec_t& tec1, const tec_t& tec2)
+{
+  return not(tec1 == tec2);
+}
+
+bool operator==(const fcbd_t& fcbd1, const fcbd_t& fcbd2)
+{
+  return fcbd1.ts == fcbd2.ts && fcbd1.te == fcbd2.te &&
+         GnssUtils::equalArray2d<double>(&fcbd1.bias[0][0],
+                                         &fcbd2.bias[0][0],
+                                         ARRAY2D_NROWS(fcbd1.bias),
+                                         ARRAY2D_NCOLS(fcbd1.bias),
+                                         ARRAY2D_NROWS(fcbd2.bias),
+                                         ARRAY2D_NCOLS(fcbd2.bias)) &&
+         GnssUtils::equalArray2d<double>(&fcbd1.std[0][0],
+                                         &fcbd2.std[0][0],
+                                         ARRAY2D_NROWS(fcbd1.std),
+                                         ARRAY2D_NCOLS(fcbd1.std),
+                                         ARRAY2D_NROWS(fcbd2.std),
+                                         ARRAY2D_NCOLS(fcbd2.std));
+}
+bool operator!=(const fcbd_t& fcbd1, const fcbd_t& fcbd2)
+{
+  return not(fcbd1 == fcbd2);
+}
+
+bool operator==(const erp_t& erp1, const erp_t& erp2)
+{
+  // TODO
+  return true;
+}
+bool operator!=(const erp_t& erp1, const erp_t& erp2)
+{
+  return not(erp1 == erp2);
+}
+
+bool operator==(const nav_t& nav1, const nav_t& nav2)
+{
+  if (nav1.n != nav2.n)
+    return false;
+  for (int i = 0; i < nav1.n; ++i)
+  {
+    if (nav1.eph[i] != nav2.eph[i])
+      return false;
+  }
+
+  if (nav1.ng != nav2.ng)
+    return false;
+  for (int i = 0; i < nav1.ng; ++i)
+  {
+    if (nav1.geph[i] != nav2.geph[i])
+      return false;
+  }
+
+  if (nav1.ns != nav2.ns)
+    return false;
+  for (int i = 0; i < nav1.ns; ++i)
+  {
+    if (nav1.seph[i] != nav2.seph[i])
+      return false;
+  }
+
+  if (nav1.ne != nav2.ne)
+    return false;
+  for (int i = 0; i < nav1.ne; ++i)
+  {
+    if (nav1.peph[i] != nav2.peph[i])
+      return false;
+  }
+
+  if (nav1.nc != nav2.nc)
+    return false;
+  for (int i = 0; i < nav1.nc; ++i)
+  {
+    if (nav1.pclk[i] != nav2.pclk[i])
+      return false;
+  }
+
+  if (nav1.na != nav2.na)
+    return false;
+  for (int i = 0; i < nav1.na; ++i)
+  {
+    if (nav1.alm[i] != nav2.alm[i])
+      return false;
+  }
+
+  if (nav1.nt != nav2.nt)
+    return false;
+  for (int i = 0; i < nav1.nt; ++i)
+  {
+    if (nav1.tec[i] != nav2.tec[i])
+      return false;
+  }
+
+  if (nav1.nf != nav2.nf)
+    return false;
+  for (int i = 0; i < nav1.nf; ++i)
+  {
+    if (nav1.fcb[i] != nav2.fcb[i])
+      return false;
+  }
+
+  // erp to do
+
+  return nav1.nmax == nav2.nmax && nav1.ngmax == nav2.ngmax && nav1.nsmax == nav2.nsmax && nav1.nemax == nav2.nemax &&
+         nav1.ncmax == nav2.ncmax && nav1.namax == nav2.namax && nav1.ntmax == nav2.ntmax && nav1.nfmax == nav2.nfmax &&
+         nav1.erp == nav2.erp &&
+         GnssUtils::equalArray<double>(
+             nav1.utc_gps, nav2.utc_gps, ARRAY_SIZE(nav1.utc_gps), ARRAY_SIZE(nav2.utc_gps)) &&
+         GnssUtils::equalArray<double>(
+             nav1.utc_glo, nav2.utc_glo, ARRAY_SIZE(nav1.utc_glo), ARRAY_SIZE(nav2.utc_glo)) &&
+         GnssUtils::equalArray<double>(
+             nav1.utc_gal, nav2.utc_gal, ARRAY_SIZE(nav1.utc_gal), ARRAY_SIZE(nav2.utc_gal)) &&
+         GnssUtils::equalArray<double>(
+             nav1.utc_qzs, nav2.utc_qzs, ARRAY_SIZE(nav1.utc_qzs), ARRAY_SIZE(nav2.utc_qzs)) &&
+         GnssUtils::equalArray<double>(
+             nav1.utc_cmp, nav2.utc_cmp, ARRAY_SIZE(nav1.utc_cmp), ARRAY_SIZE(nav2.utc_cmp)) &&
+         GnssUtils::equalArray<double>(
+             nav1.utc_irn, nav2.utc_irn, ARRAY_SIZE(nav1.utc_irn), ARRAY_SIZE(nav2.utc_irn)) &&
+         GnssUtils::equalArray<double>(
+             nav1.utc_sbs, nav2.utc_sbs, ARRAY_SIZE(nav1.utc_sbs), ARRAY_SIZE(nav2.utc_sbs)) &&
+         GnssUtils::equalArray<double>(
+             nav1.ion_gps, nav2.ion_gps, ARRAY_SIZE(nav1.ion_gps), ARRAY_SIZE(nav2.ion_gps)) &&
+         GnssUtils::equalArray<double>(
+             nav1.ion_gal, nav2.ion_gal, ARRAY_SIZE(nav1.ion_gal), ARRAY_SIZE(nav2.ion_gal)) &&
+         GnssUtils::equalArray<double>(
+             nav1.ion_qzs, nav2.ion_qzs, ARRAY_SIZE(nav1.ion_qzs), ARRAY_SIZE(nav2.ion_qzs)) &&
+         GnssUtils::equalArray<double>(
+             nav1.ion_cmp, nav2.ion_cmp, ARRAY_SIZE(nav1.ion_cmp), ARRAY_SIZE(nav2.ion_cmp)) &&
+         GnssUtils::equalArray<double>(
+             nav1.ion_irn, nav2.ion_irn, ARRAY_SIZE(nav1.ion_irn), ARRAY_SIZE(nav2.ion_irn)) &&
+         nav1.leaps == nav2.leaps &&
+         GnssUtils::equalArray2d<double>(&nav1.lam[0][0],
+                                         &nav2.lam[0][0],
+                                         ARRAY2D_NROWS(nav1.lam),
+                                         ARRAY2D_NCOLS(nav1.lam),
+                                         ARRAY2D_NROWS(nav2.lam),
+                                         ARRAY2D_NCOLS(nav2.lam)) &&
+         GnssUtils::equalArray2d<double>(&nav1.cbias[0][0],
+                                         &nav2.cbias[0][0],
+                                         ARRAY2D_NROWS(nav1.cbias),
+                                         ARRAY2D_NCOLS(nav1.cbias),
+                                         ARRAY2D_NROWS(nav2.cbias),
+                                         ARRAY2D_NCOLS(nav2.cbias)) &&
+         GnssUtils::equalArray3d<double>(&nav1.rbias[0][0][0], &nav2.rbias[0][0][0], MAXRCV, 2, 3, MAXRCV, 2, 3) &&
+         GnssUtils::equalArray<double>(nav1.wlbias, nav2.wlbias, ARRAY_SIZE(nav1.wlbias), ARRAY_SIZE(nav2.wlbias)) &&
+         GnssUtils::equalArray<double>(
+             nav1.glo_cpbias, nav2.glo_cpbias, ARRAY_SIZE(nav1.glo_cpbias), ARRAY_SIZE(nav2.glo_cpbias)) &&
+         GnssUtils::equalArray<char>(nav1.glo_fcn, nav2.glo_fcn, ARRAY_SIZE(nav1.glo_fcn), ARRAY_SIZE(nav2.glo_fcn));
+}
+bool operator!=(const nav_t& nav1, const nav_t& nav2)
+{
+  return not(nav1 == nav2);
+}
\ No newline at end of file
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 171992abf5ce4898215379e0e2aefe609dd3a7e7..e7ef282189d9297ca55770cbad6e797b36cad125 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -18,4 +18,8 @@ target_link_libraries(gtest_transformations ${PROJECT_NAME})
 
 # Observations test
 gnss_utils_add_gtest(gtest_observations gtest_observations.cpp)
-target_link_libraries(gtest_observations libgtest ${PROJECT_NAME})
\ No newline at end of file
+target_link_libraries(gtest_observations libgtest ${PROJECT_NAME})
+
+# Navigation test
+gnss_utils_add_gtest(gtest_navigation gtest_navigation.cpp)
+target_link_libraries(gtest_navigation libgtest ${PROJECT_NAME})
\ No newline at end of file
diff --git a/test/gtest_navigation.cpp b/test/gtest_navigation.cpp
index 5170cf11310248899fd967b3b870f974a6368b2f..359e44eadaedbcf266f243a6268d17d188cf9b08 100644
--- a/test/gtest_navigation.cpp
+++ b/test/gtest_navigation.cpp
@@ -1,12 +1,35 @@
 #include "gtest/utils_gtest.h"
-#include "gnss_utils/gnss_utils.h"
+#include "gnss_utils/utils/utils.h"
+#include "gnss_utils/navigation.h"
 
-TEST(NavigationTests, Whatever)
+using namespace GnssUtils;
+std::string   rnx_file = std::string(_GNSS_UTILS_ROOT_DIR) + "/test/data/sample_data.nav";
+const gtime_t t_start{ 0, 0 };  // no limit
+const gtime_t t_end{ 0, 0 };    // no limit
+const double  dt  = 0.0;        // no limit
+const char*   opt = "";         // only GPS | GPS+GAL: "-SYS=G,L" | ALL: ""
+
+void loadRinex(nav_t& nav)
 {
-  
+  int stat = readrnxt(rnx_file.c_str(), 1, t_start, t_end, dt, opt, NULL, &nav, NULL);
+
+  ASSERT_EQ(stat, 1);
+  uniqnav(&nav);
+}
+
+TEST(NavigationTests, setgetNavigation)
+{
+  nav_t nav;
+  loadRinex(nav);
+
+  Navigation navigation;
+
+  navigation.setNavigation(nav);
+  ASSERT_TRUE(navigation.getNavigation() == nav);
+  Navigation::freeNavArrays(nav);
 }
 
-int main(int argc, char **argv)
+int main(int argc, char** argv)
 {
   testing::InitGoogleTest(&argc, argv);
   return RUN_ALL_TESTS();
diff --git a/test/gtest_observations.cpp b/test/gtest_observations.cpp
index d64de85415cc59e7c5d33d559cc842d334ab46f6..cbb25d72d1863ea094dd2bd83cc28c3a8f60a5d6 100644
--- a/test/gtest_observations.cpp
+++ b/test/gtest_observations.cpp
@@ -3,13 +3,12 @@
 
 using namespace GnssUtils;
 std::string   rnx_file = std::string(_GNSS_UTILS_ROOT_DIR) + "/test/data/sample_data.obs";
-obs_t         obs;
 const gtime_t t_start{ 0, 0 };  // no limit
 const gtime_t t_end{ 0, 0 };    // no limit
 const double  dt  = 0.0;        // no limit
-const char*   opt = "-SYS=G";   // only GPS | GPS+GAL: "-SYS=G,L" | ALL: ""
+const char*   opt = "";         // only GPS | GPS+GAL: "-SYS=G,L" | ALL: ""
 
-void loadRinex()
+void loadRinex(obs_t& obs)
 {
   // RTKLIB utilities
   obs.data = (obsd_t*)malloc(sizeof(obsd_t) * MAXSAT);
@@ -24,7 +23,8 @@ void loadRinex()
 
 TEST(ObservationsTest, AddClearObservation)
 {
-  loadRinex();
+  obs_t obs;
+  loadRinex(obs);
 
   Observations observations;
 
@@ -44,19 +44,20 @@ TEST(ObservationsTest, AddClearObservation)
 
   // Add duplicated observation (has to crash)
   observations.addObservation(obs.data[0]);
-  ASSERT_DEATH(observations.addObservation(obs.data[0]),"");
+  ASSERT_DEATH(observations.addObservation(obs.data[0]), "");
 }
 
 TEST(ObservationsTest, LoadFromRinex)
 {
+  // RTKLIB utilities
+  obs_t obs;
+  loadRinex(obs);
+
   // GnssUtils utilities
   Observations observations;
   observations.loadFromRinex(rnx_file.c_str(), t_start, t_end, dt, opt);
-  observations.print();
 
-  // RTKLIB utilities
-  loadRinex();
-  ASSERT_EQ(obs.n, 6);
+  ASSERT_EQ(obs.n, 18);
 
   // Comparison
   ASSERT_TRUE(obs.n == observations.getObservations().size());
@@ -70,7 +71,8 @@ TEST(ObservationsTest, LoadFromRinex)
 
 TEST(ObservationsTest, GetObservationBySat)
 {
-  loadRinex();
+  obs_t obs;
+  loadRinex(obs);
 
   Observations observations;
   observations.loadFromRinex(rnx_file.c_str(), t_start, t_end, dt, opt);
@@ -79,39 +81,41 @@ TEST(ObservationsTest, GetObservationBySat)
   {
     ASSERT_TRUE(obs.data[ii] == observations.getObservationBySat(obs.data[ii].sat));
   }
+  free(obs.data);
 }
 
 TEST(ObservationsTest, GetObservationByIdx)
 {
-  loadRinex();
+  obs_t obs;
+  loadRinex(obs);
 
   Observations observations;
   observations.loadFromRinex(rnx_file.c_str(), t_start, t_end, dt, opt);
 
   for (int ii = 0; ii < obs.n; ++ii)
   {
-    // We do this check like this because both loading functions load the rinex file and then sort the observations
-    ASSERT_TRUE( obs.data[ii] == observations.getObservationByIdx(ii));
+    ASSERT_TRUE(obs.data[ii] == observations.getObservationByIdx(ii));
   }
 }
 
 TEST(ObservationsTest, data)
 {
-  loadRinex();
+  obs_t obs;
+  loadRinex(obs);
 
   Observations observations;
   observations.loadFromRinex(rnx_file.c_str(), t_start, t_end, dt, opt);
 
   for (int ii = 0; ii < obs.n; ++ii)
   {
-    // We do this check like this because both loading functions load the rinex file and then sort the observations
-    ASSERT_TRUE( obs.data[ii] == observations.data()[ii]);
+    ASSERT_TRUE(obs.data[ii] == observations.data()[ii]);
   }
 }
 
 TEST(ObservationsTest, HasSatellite)
 {
-  loadRinex();
+  obs_t obs;
+  loadRinex(obs);
 
   Observations observations;
   observations.loadFromRinex(rnx_file.c_str(), t_start, t_end, dt, opt);
@@ -171,7 +175,7 @@ TEST(ObservationsTest, FindCommonObservationsChangeTime)
   // Change time
   for (auto&& obs : observations2.getObservations())
   {
-      obs.time.sec +=10;
+    obs.time.sec += 10;
   }
 
   std::set<int> common_sats = Observations::findCommonObservations(observations1, observations2);
@@ -188,6 +192,6 @@ TEST(ObservationsTest, FindCommonObservationsChangeTime)
 int main(int argc, char** argv)
 {
   testing::InitGoogleTest(&argc, argv);
-  //rnx_file = argv[1];
+  // rnx_file = argv[1];
   return RUN_ALL_TESTS();
 }