Repository: ORNL/DataFed (language: python)

Issue:
Essentially started adding a test for the json object and also fixed …
…the bug

* [x] - Added initial unit test code for common libjson 
* [x] - Added fix to GlobusAPI file
* [x] - Reduced default logging output
* [x] - Updated CHANGELOG


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index ead16e18d..ea288ff1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,8 @@ repository/server/Version.hpp
 scripts/globus/datafed-home-repo.sh
 scripts/globus/datafed-home-repo-form.json
 scripts/globus/mapping.json
+scripts/admin_datafed_backup.sh
+scripts/admin_refresh_certs.sh
 services/
 web/SDMS.proto
 web/SDMS_Anon.proto
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 0f50da431..4678335a3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -285,9 +285,10 @@ end-to-end-ws-setup:
     - CERT_FILE_NAME=$(basename "${CI_DATAFED_WEB_CERT_PATH}")
     - KEY_FILE_NAME=$(basename "${CI_DATAFED_WEB_KEY_PATH}")
     - ./scripts/container_stop.sh -t "code.ornl.gov:4567/${IMAGE_TAG}${BRANCH_LOWER}"
+    - random_string=$(bash -c "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "10" | head -n 1")
     - >
       docker run -d
-      --name "ws-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}"
+      --name "ws-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}"
       -e DATAFED_GLOBUS_APP_SECRET="GLOBUS_DATAFED_APP_SECRET"
       -e DATAFED_GLOBUS_APP_ID="$GLOBUS_DATAFED_APP_ID"
       -e DATAFED_ZEROMQ_SESSION_SECRET="$DATAFED_ZEROMQ_SESSION_SECRET"
@@ -324,9 +325,10 @@ end-to-end-core-setup:
     - ./scripts/generate_datafed.sh
     - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN code.ornl.gov:4567
     - ./scripts/container_stop.sh -t "code.ornl.gov:4567/${IMAGE_TAG}${BRANCH_LOWER}"
+    - random_string=$(bash -c "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "10" | head -n 1")
     - >
       docker run -d
-      --name "core-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}"
+      --name "core-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}"
       -e DATAFED_GLOBUS_APP_SECRET="$CI_DATAFED_GLOBUS_APP_SECRET"
       -e DATAFED_GLOBUS_APP_ID="$CI_DATAFED_GLOBUS_APP_ID"
       -e DATAFED_ZEROMQ_SESSION_SECRET="$CI_DATAFED_ZEROMQ_SESSION_SECRET"
@@ -348,6 +350,7 @@ end-to-end-repo-setup:
     IMAGE_TAG: "dlsw/datafed/repo-"
     GIT_STRATEGY: clone
     HOST_LOG_FILE_PATH: "$CI_PROJECT_DIR/logs"
+    CONTAINER_LOG_FILE_PATH: "/datafed/logs"
   stage: end-to-end-setup
   tags:
     - ci-datafed-globus
@@ -360,15 +363,16 @@ end-to-end-repo-setup:
     - ./scripts/generate_datafed.sh
     - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN code.ornl.gov:4567
     - ./scripts/container_stop.sh -t "code.ornl.gov:4567/${IMAGE_TAG}${BRANCH_LOWER}"
+    - random_string=$(bash -c "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "10" | head -n 1")
     - >
       docker run -d
-      --name "repo-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}"
+      --name "repo-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}"
       -e DATAFED_GLOBUS_APP_SECRET="$CI_DATAFED_GLOBUS_APP_SECRET"
       -e DATAFED_GLOBUS_APP_ID="$CI_DATAFED_GLOBUS_APP_ID"
       -e DATAFED_ZEROMQ_SESSION_SECRET="$CI_DATAFED_ZEROMQ_SESSION_SECRET"
       -e DATAFED_ZEROMQ_SYSTEM_SECRET="$CI_DATAFED_ZEROMQ_SYSTEM_SECRET"
       -e DATAFED_DOMAIN="$CI_DATAFED_DOMAIN"
-      -v "$HOST_LOG_FILE_PATH:/var/log/datafed/datafed-ws.log"
+      -v "${HOST_LOG_FILE_PATH}:${CONTAINER_LOG_FILE_PATH}"
       -v "$CI_DATAFED_REPO_PUB_KEY":/source/install/keys/datafed-repo-key.pub
       -v "$CI_DATAFED_REPO_PRIV_KEY":/source/install/keys/datafed-repo-key.priv
       -t "code.ornl.gov:4567/${IMAGE_TAG}${BRANCH_LOWER}" 
@@ -378,6 +382,7 @@ end-to-end-gcs-authz-setup:
   variables:
     IMAGE_TAG: "dlsw/datafed/gcs-authz-"
     HOST_LOG_FILE_PATH: "$CI_PROJECT_DIR/logs"
+    CONTAINER_LOG_FILE_PATH: "/datafed/logs"
     GIT_STRATEGY: clone
   stage: end-to-end-setup
   tags:
@@ -391,15 +396,16 @@ end-to-end-gcs-authz-setup:
     - ./scripts/generate_datafed.sh
     - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN code.ornl.gov:4567
     - ./scripts/container_stop.sh -t "code.ornl.gov:4567/${IMAGE_TAG}${BRANCH_LOWER}"
+    - random_string=$(bash -c "cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w "10" | head -n 1")
     - >
       docker run -d
-      --name "gcs-authz-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}"
+      --name "gcs-authz-${BRANCH_LOWER}-${CI_COMMIT_SHORT_SHA}-${random_string}"
       -e DATAFED_GLOBUS_APP_SECRET="$CI_DATAFED_GLOBUS_APP_SECRET"
       -e DATAFED_GLOBUS_APP_ID="$CI_DATAFED_GLOBUS_APP_ID"
       -e DATAFED_ZEROMQ_SESSION_SECRET="$CI_DATAFED_ZEROMQ_SESSION_SECRET"
       -e DATAFED_ZEROMQ_SYSTEM_SECRET="$CI_DATAFED_ZEROMQ_SYSTEM_SECRET"
       -e DATAFED_DOMAIN="$CI_DATAFED_DOMAIN"
-      -v "$HOST_LOG_FILE_PATH:/var/log/datafed/datafed-ws.log"
+      -v "${HOST_LOG_FILE_PATH}:${CONTAINER_LOG_FILE_PATH}"
       -v "$CI_DATAFED_REPO_PUB_KEY":/source/install/keys/datafed-repo-key.pub
       -v "$CI_DATAFED_REPO_PRIV_KEY":/source/install/keys/datafed-repo-key.priv
       -t "code.ornl.gov:4567/${IMAGE_TAG}${BRANCH_LOWER}" 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4cbf4f0a8..da9bb813c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,20 @@
-# Pre-Release
+# Pre-release
 
+## MAJOR Breaking changes
 
 ## PATCH Bug fixes/Technical Debt/Documentation
 1. [911] - Add GitHub template
 2. [910] - Static code analysis and status checks fixed, improvements to CI
 
+# v2023.10.23.15.50
+
+## MINOR Feature
+1. [906] - Added backup and cert refresh scripts. 
+
+## PATCH Bug Fixes/Technical Debt/Documentation
+1. [911] - Add GitHub template
+2. [913] - Fixed bug, when endpoint info returns an empty array check to seee if array is empty before accessing elements
+
 # v2023.8.21.10.40
 
 ## MAJOR Breaking changes
@@ -20,7 +30,7 @@
 7. [879] - Added correlation ids to messages for tracking
 8. [879] - Split log output into server specific files.
 
-## PATCH Bug fixes/Technical Debt/Documentation
+## PATCH Bug Fixes/Technical Debt/Documentation
 1. [879] - Fixed thread safety of repo list calls in core server which where causing
 seg faults
 2. [879] - Added better error reporting when attempting to delete repo with running tasks.
diff --git a/common/include/common/libjson.hpp b/common/include/common/libjson.hpp
index 5fad1ddb0..4c353a663 100644
--- a/common/include/common/libjson.hpp
+++ b/common/include/common/libjson.hpp
@@ -674,16 +674,20 @@ class Value {
   }
 
   Object &asObject() {
-    if (m_type != VT_OBJECT)
-      EXCEPT(1, "Value is not an object");
-
+    if (m_type != VT_OBJECT) {
+      std::string error_msg = "Value is not an object, it is instead of type: ";
+      error_msg += getTypeString();
+      EXCEPT(1, error_msg);
+    }
     return *m_value.o;
   }
 
   const Object &asObject() const {
-    if (m_type != VT_OBJECT)
-      EXCEPT(1, "Value is not an object");
-
+    if (m_type != VT_OBJECT) {
+      std::string error_msg = "Value is not an object, it is instead of type: ";
+      error_msg += getTypeString();
+      EXCEPT(1, error_msg);
+    }
     return *m_value.o;
   }
 
@@ -698,15 +702,21 @@ class Value {
   }
 
   Array &asArray() {
-    if (m_type != VT_ARRAY)
-      EXCEPT(1, "Value is not an array");
+    if (m_type != VT_ARRAY) {
+      std::string error_msg = "Value is not an array, it is instead of type: ";
+      error_msg += getTypeString();
+      EXCEPT(1, error_msg);
+    }
 
     return *m_value.a;
   }
 
   const Array &asArray() const {
-    if (m_type != VT_ARRAY)
-      EXCEPT(1, "Value is not an array");
+    if (m_type != VT_ARRAY) {
+      std::string error_msg = "Value is not an array, it is instead of type: ";
+      error_msg += getTypeString();
+      EXCEPT(1, error_msg);
+    }
 
     return *m_value.a;
   }
diff --git a/core/server/GlobusAPI.cpp b/core/server/GlobusAPI.cpp
index 08b5158a3..c6c7be428 100644
--- a/core/server/GlobusAPI.cpp
+++ b/core/server/GlobusAPI.cpp
@@ -542,12 +542,11 @@ void GlobusAPI::getEndpointInfo(const std::string &a_ep_id,
   long code = get(m_curl_xfr, m_config.glob_xfr_url + "endpoint/", a_ep_id,
                   a_acc_token, {}, raw_result);
 
+  Value result;
   try {
     if (!raw_result.size())
       EXCEPT_PARAM(ID_SERVICE_ERROR, "Empty response. Code: " << code);
 
-    Value result;
-
     result.fromString(raw_result);
 
     Value::Object &resp_obj = result.asObject();
@@ -575,15 +574,18 @@ void GlobusAPI::getEndpointInfo(const std::string &a_ep_id,
 
       // Look at DATA[0].scheme to see if it's gsiftp
       Value::Array &data = resp_obj.getArray("DATA");
-      Value::Object &server_obj = data[0].asObject();
 
-      Value &scheme = server_obj.getValue("scheme");
+      if (data.size() > 0) {
+        Value::Object &server_obj = data[0].asObject();
 
-      if (scheme.isNull())
-        a_ep_info.supports_encryption = true;
-      else if (scheme.isString())
-        a_ep_info.supports_encryption =
-            (scheme.asString().compare("gsiftp") == 0);
+        Value &scheme = server_obj.getValue("scheme");
+
+        if (scheme.isNull())
+          a_ep_info.supports_encryption = true;
+        else if (scheme.isString())
+          a_ep_info.supports_encryption =
+              (scheme.asString().compare("gsiftp") == 0);
+      }
     }
   } catch (libjson::ParseError &e) {
     DL_ERROR(m_log_context, "PARSE FAILED! " << raw_result);
@@ -591,6 +593,7 @@ void GlobusAPI::getEndpointInfo(const std::string &a_ep_id,
                  "Globus endpoint API call returned invalid JSON.");
   } catch (TraceException &e) {
     DL_ERROR(m_log_context, raw_result);
+    DL_ERROR(m_log_context, "Result type: " << result.getTypeString());
     e.addContext("Globus endpoint API call failed.");
     throw;
   } catch (exception &e) {
diff --git a/core/server/main.cpp b/core/server/main.cpp
index 809f4a3c1..b75ac294d 100644
--- a/core/server/main.cpp
+++ b/core/server/main.cpp
@@ -30,7 +30,7 @@ namespace po = boost::program_options;
 int main(int a_argc, char **a_argv) {
   global_logger.setSysLog(false);
   global_logger.addStream(std::cerr);
-  global_logger.setLevel(LogLevel::DEBUG);
+  global_logger.setLevel(LogLevel::INFO);
   LogContext log_context;
   log_context.thread_name = "core_server";
   log_context.thread_id = 0;
diff --git a/scripts/generate_certificate_refresh_script.sh b/scripts/generate_certificate_refresh_script.sh
new file mode 100755
index 000000000..3725441b8
--- /dev/null
+++ b/scripts/generate_certificate_refresh_script.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+# Cannot run with -u because we check for unbound variables
+# and the script will exit prematurely if '-u' is set
+set -ef -o pipefail
+
+SCRIPT=$(realpath "$0")
+FILE_NAME=$(basename "${SCRIPT}")
+SOURCE=$(dirname "$SCRIPT")
+PROJECT_ROOT=$(realpath "${SOURCE}/..")
+source "${PROJECT_ROOT}/config/datafed.sh"
+
+VERSION="1.0.0"
+echo "$FILE_NAME $VERSION"
+
+ERROR_DETECTED=0
+if [ -z "$DATAFED_INSTALL_PATH" ]
+then
+  echo "Error DATAFED_INSTALL_PATH is not defined in config/datafed.sh, this is"
+  echo "      a required argument."
+  ERROR_DETECTED=1
+fi
+
+if [ -z "$DATAFED_LEGO_EMAIL" ]
+then
+  echo "Error DATAFED_LEGO_EMAIL is not defined in config/datafed.sh, this is"
+  echo "      a required argument."
+  ERROR_DETECTED=1
+fi
+
+if [ -z "$DATAFED_DOMAIN" ]
+then
+  echo "Error DATAFED_DOMAIN is not defined in config/datafed.sh, this is"
+  echo "      a required argument."
+  ERROR_DETECTED=1
+fi
+
+if [ "$ERROR_DETECTED" == "1" ]
+then
+  exit 1
+fi
+
+cat << OUTER_EOF > "$PROJECT_ROOT/scripts/admin_refresh_certs.sh"
+#!/bin/bash
+
+# NOTE this script is generated by $SCRIPT, to recreate it change
+# settings in datafed.sh and rerun $SCRIPT.
+#
+# You will still need to make sure this script is registered in cron
+# sudo crontab -e
+# 0 0 * */2 0 ${DATAFED_INSTALL_PATH}/scripts/admin_refresh_certs.sh
+# This script will run every second month if configured in cron with the above
+# settings.
+# This script should be run with 755 permissions
+# and root root
+DOMAIN="${DATAFED_DOMAIN}"
+systemctl stop datafed-ws.service
+lego --email="${DATAFED_LEGO_EMAIL}" --domains="${DATAFED_DOMAIN}" --tls run
+DIR_NAME=\$(date +%m-%Y)
+mkdir -p "\${DIR_NAME}"
+# Create a copy so we can always go back and check when the last time was
+# that the job ran successfully
+cp ".lego/certificates/${DATAFED_DOMAIN}.key" "\${DIR_NAME}"
+cp ".lego/certificates/${DATAFED_DOMAIN}.crt" "\${DIR_NAME}"
+mv ".lego/certificates/${DATAFED_DOMAIN}.key" ${DATAFED_INSTALL_PATH}/keys/
+mv ".lego/certificates/${DATAFED_DOMAIN}.crt" ${DATAFED_INSTALL_PATH}/keys/
+chmod 600 "${DATAFED_INSTALL_PATH}/keys/${DATAFED_DOMAIN}.key"
+chmod 600 "${DATAFED_INSTALL_PATH}/keys/${DATAFED_DOMAIN}.crt"
+chown root "${DATAFED_INSTALL_PATH}/keys/${DATAFED_DOMAIN}.crt"
+chgrp root "${DATAFED_INSTALL_PATH}/keys/${DATAFED_DOMAIN}.crt"
+chown root "${DATAFED_INSTALL_PATH}/keys/${DATAFED_DOMAIN}.key"
+chgrp root "${DATAFED_INSTALL_PATH}/keys/${DATAFED_DOMAIN}.key"
+systemctl start datafed-ws.service
+
+sendmail "$DATAFED_ADMIN_EMAIL" << EOF
+To: $DATAFED_ADMIN_EMAIL
+From: $DATAFED_SYSTEM_EMAIL
+Subject: DataFed Certificate Update
+
+DataFed has updated the web certificates.
+EOF
+OUTER_EOF
+
+chmod 755  "$PROJECT_ROOT/scripts/admin_refresh_certs.sh"
diff --git a/scripts/generate_datafed.sh b/scripts/generate_datafed.sh
index ccb3138ef..7d889bacb 100755
--- a/scripts/generate_datafed.sh
+++ b/scripts/generate_datafed.sh
@@ -175,21 +175,27 @@ export DATAFED_GLOBUS_APP_SECRET="$local_DATAFED_GLOBUS_APP_SECRET"
 # ************************************************
 # i.e. 7512 - ZeroMQ port
 export DATAFED_SERVER_PORT="$local_DATAFED_SERVER_PORT"
+
 # ************************************************
 # Env Variables for Authz, Web, Repo Server
 # ************************************************
-# If not set will resolve to datafed.ornl.gov
-export DATAFED_DOMAIN="$local_DATAFED_DOMAIN"
 # DataFed Repository POSIX user account that DataFed users will be mapped too
 # from Globus, so the posix account all globus users will map too
 export DATAFED_GLOBUS_REPO_USER=""
 
+# ******************************************************************
+# Env Variables for Authz, Web, Repo Server & administrative scripts
+# ******************************************************************
+# If not set will resolve to datafed.ornl.gov
+export DATAFED_DOMAIN="$local_DATAFED_DOMAIN"
+
 # ************************************************
 # Env Variables for Core Server
 # ************************************************
 export DATAFED_DATABASE_PASSWORD="$local_DATAFED_DATABASE_PASSWORD"
 # The user account the datafed core application will run under
 export DATAFED_CORE_USER=""
+
 # ************************************************
 # Env Variables for Web Server
 # ************************************************
@@ -206,6 +212,18 @@ export DATAFED_WEB_CERT_PATH="$local_DATAFED_WEB_CERT_PATH"
 export DATAFED_WEB_USER=""
 # How the web server communicates with the core server, assumes an internal network
 export DATAFED_CORE_ADDRESS_PORT_INTERNAL="$local_DATAFED_CORE_ADDRESS_PORT_INTERNAL"
+
+# ****************************************************************************
+# Env Variables for DataFed Core server administrative and operational scripts 
+# ****************************************************************************
+# The admin should who should be receiving emails about the backups
+export DATAFED_ADMIN_EMAIL=""
+# DataFed system email is from the actual system not from a person, it is
+# used to fill in the from field when sending emails out to admins or users.
+export DATAFED_SYSTEM_EMAIL=""
+# Where the database backups will be placed.
+export DATAFED_DATABASE_BACKUP_PATH=""
+
 # ************************************************
 # Env Variables for Globus Connect Server
 # ************************************************
diff --git a/scripts/generate_datafed_backup_script.sh b/scripts/generate_datafed_backup_script.sh
new file mode 100755
index 000000000..64ec9ca4b
--- /dev/null
+++ b/scripts/generate_datafed_backup_script.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+
+# Cannot run with -u because we check for unbound variables
+# and the script will exit prematurely if '-u' is set
+set -ef -o pipefail
+
+SCRIPT=$(realpath "$0")
+FILE_NAME=$(basename "${SCRIPT}")
+SOURCE=$(dirname "$SCRIPT")
+PROJECT_ROOT=$(realpath "${SOURCE}/..")
+source "${PROJECT_ROOT}/config/datafed.sh"
+
+VERSION="1.0.0"
+echo "$FILE_NAME $VERSION"
+
+ERROR_DETECTED=0
+# The admin should who should be receiving emails about the backups
+if [ -z "$DATAFED_ADMIN_EMAIL" ]
+then
+  echo "Error DATAFED_ADMIN_EMAIL is not defined, this is a required argument."
+  ERROR_DETECTED=1
+fi
+
+# DataFed system email is from the actual system not from a person, it is
+# used to fill in the from field when sending emails out to admins or users.
+if [ -z "$DATAFED_SYSTEM_EMAIL" ]
+then
+  echo "Error DATAFED_SYSTEM_EMAIL is not defined, this is a required argument"
+  ERROR_DETECTED=1
+fi
+
+# Where the database backups will be placed.
+if [ -z "$DATAFED_DATABASE_BACKUP_PATH" ]
+then
+  echo "Error DATAFED_DATABASE_BACKUP_PATH is not defined, this is a required argument"
+  ERROR_DETECTED=1
+fi
+
+if [ "$ERROR_DETECTED" == "1" ]
+then
+  exit 1
+fi
+
+cat << OUTER_EOF > "$PROJECT_ROOT/scripts/admin_datafed_backup.sh"
+#!/bin/bash
+
+# This script needs to be registered in the crontab
+# 45 23 * * 0 ${DATAFED_INSTALL_PATH}/scripts/admin_datafed-backup.sh
+# This will run at 11:45 pm every sunday night
+# If need to send mail to SMTP machine
+
+# NOTE this script is generated by $SCRIPT, to recreate it change
+# settings in datafed.sh and rerun $SCRIPT.
+echo "DataFed - running DB backup"
+
+# Shutdown DataFed services
+systemctl stop globus-gridftp-server.service
+systemctl stop datafed-ws.service
+systemctl stop datafed-repo.service
+systemctl stop datafed-core.service
+systemctl stop arangodb3.service
+
+backup_file=DataFed_DB_Backup_\$(date +"%Y_%m_%d").tar.gz
+
+# Tar contents of arangodb directory without full path
+tar -C /var/lib/arangodb3 -cvzf \${backup_file} .
+
+# Move backup file to storage location
+mv \${backup_file} ${DATAFED_DATABASE_BACKUP_PATH}/backups
+
+# Restart DataFed services
+systemctl start arangodb3.service
+systemctl start datafed-core.service
+systemctl start globus-gridftp-server.service
+systemctl start datafed-repo.service
+systemctl start datafed-ws.service
+
+echo "DataFed - backup completed"
+
+sendmail "$DATAFED_ADMIN_EMAIL" << EOF
+To: $DATAFED_ADMIN_EMAIL
+From: $DATAFED_SYSTEM_EMAIL
+Subject: DataFed Database Backup Notification
+
+DataFed has been backed up. A new backup exists at ${DATAFED_DATABASE_BACKUP_PATH}/backups.
+EOF
+OUTER_EOF
+
+chmod +x "$PROJECT_ROOT/scripts/admin_datafed_backup.sh"


Test patch:
diff --git a/common/tests/unit/CMakeLists.txt b/common/tests/unit/CMakeLists.txt
index 298de375d..52fb4b748 100644
--- a/common/tests/unit/CMakeLists.txt
+++ b/common/tests/unit/CMakeLists.txt
@@ -4,6 +4,7 @@ foreach(PROG
     test_CommunicatorFactory
     test_Frame
     test_DynaLog
+    test_Value
     test_MessageFactory
     test_OperatorFactory
     test_ProtoBufFactory
diff --git a/common/tests/unit/test_Value.cpp b/common/tests/unit/test_Value.cpp
new file mode 100644
index 000000000..2b5e1601f
--- /dev/null
+++ b/common/tests/unit/test_Value.cpp
@@ -0,0 +1,134 @@
+#define BOOST_TEST_MAIN
+
+#define BOOST_TEST_MODULE libjson
+#include <boost/filesystem.hpp>
+#include <boost/test/unit_test.hpp>
+
+// Local public includes
+#include "common/DynaLog.hpp"
+#include "common/TraceException.hpp"
+#include "common/libjson.hpp"
+
+// Standard includes
+#include <iostream>
+#include <string>
+
+// using namespace SDMS;
+
+BOOST_AUTO_TEST_SUITE(LibJSONTest)
+
+BOOST_AUTO_TEST_CASE(testing_object) {
+
+  std::string raw_result = "{\n";
+  raw_result += "  \"DATA\": [],\n";
+  raw_result += "  \"DATA_TYPE\": \"endpoint\",\n";
+  raw_result += "  \"acl_available\": true,\n";
+  raw_result += "  \"acl_editable\": false,\n";
+  raw_result += "  \"activated\": false,\n";
+  raw_result += "  \"authentication_assurance_timeout\": null,\n";
+  raw_result += "  \"authentication_policy_id\": null,\n";
+  raw_result += "  \"authentication_timeout_mins\": null,\n";
+  raw_result += "  \"canonical_name\": "
+                "\"u_t2uyxwqjgvapzmwlfahbi5l4mq#11bc8bd6-6b22-11eb-8287-"
+                "0275e0cda761\",\n";
+  raw_result += "  \"contact_email\": \"researchcomputing@mara.edu\",\n";
+  raw_result += "  \"contact_info\": null,\n";
+  raw_result += "  \"default_directory\": \"/{server_default}/\",\n";
+  raw_result += "  \"department\": \"Research Computing\",\n";
+  raw_result += "  \"description\": \"Library Published Data\",\n";
+  raw_result += "  \"disable_anonymous_writes\": false,\n";
+  raw_result += "  \"disable_verify\": false,\n";
+  raw_result += "  \"display_name\": \"New Anonymous Endpoint\",\n";
+  raw_result += "  \"entity_type\": \"GCSv5_guest_collection\",\n";
+  raw_result += "  \"expire_time\": null,\n";
+  raw_result += "  \"expires_in\": -1,\n";
+  raw_result += "  \"force_encryption\": false,\n";
+  raw_result += "  \"force_verify\": false,\n";
+  raw_result += "  \"french_english_bilingual\": false,\n";
+  raw_result += "  \"gcp_connected\": null,\n";
+  raw_result += "  \"gcp_paused\": null,\n";
+  raw_result +=
+      "  \"gcs_manager_url\": \"https://e878b.bd7c.data.globus.org\",\n";
+  raw_result += "  \"gcs_version\": \"5.4.67\",\n";
+  raw_result += "  \"globus_connect_setup_key\": null,\n";
+  raw_result += "  \"high_assurance\": false,\n";
+  raw_result += "  \"host_endpoint\": "
+                "\"u_t2uyxwqjglapzmwbfahbi5l4mq#3b3f5c6c-5b6a-11eb-87bf-"
+                "02187389bd35\",\n";
+  raw_result += "  \"host_endpoint_display_name\": \"net01\",\n";
+  raw_result +=
+      "  \"host_endpoint_id\": \"9ea98bda-0135-40fc-b2c1-280e14757c64\",\n";
+  raw_result += "  \"host_path\": null,\n";
+  raw_result +=
+      "  \"https_server\": \"https://g-f09197.e778b.bd7c.data.globus.org\",\n";
+  raw_result += "  \"id\": \"e1d2afd2-ce11-4482-b127-b4cceef666f6\",\n";
+  raw_result += "  \"in_use\": false,\n";
+  raw_result += "  \"info_link\": null,\n";
+  raw_result += "  \"is_globus_connect\": false,\n";
+  raw_result += "  \"is_go_storage\": false,\n";
+  raw_result += "  \"keywords\": \"Uni,State,Top\",\n";
+  raw_result += "  \"last_accessed_time\": \"2023-10-23T00:00:00+00:00\",\n";
+  raw_result += "  \"local_user_info_available\": true,\n";
+  raw_result += "  \"location\": null,\n";
+  raw_result +=
+      "  \"mapped_collection_display_name\": \"New Published Data\",\n";
+  raw_result +=
+      "  \"mapped_collection_id\": \"5b52029b-9a3e-4490-abcf-649dd2f4fd6c\",\n";
+  raw_result += "  \"max_concurrency\": null,\n";
+  raw_result += "  \"max_parallelism\": null,\n";
+  raw_result += "  \"mfa_required\": false,\n";
+  raw_result += "  \"my_effective_roles\": [],\n";
+  raw_result += "  \"myproxy_dn\": null,\n";
+  raw_result += "  \"myproxy_server\": \"myproxy.globusonline.org\",\n";
+  raw_result += "  \"name\": \"11bc8bd6-6b22-11eb-8287-0275e0cda761\",\n";
+  raw_result += "  \"network_use\": null,\n";
+  raw_result += "  \"non_functional\": false,\n";
+  raw_result += "  \"non_functional_endpoint_display_name\": \"net01\",\n";
+  raw_result += "  \"non_functional_endpoint_id\": "
+                "\"9ea98bda-0935-40fc-b2c1-280e14757c64\",\n";
+  raw_result += "  \"oauth_server\": null,\n";
+  raw_result += "  \"organization\": \"The new University\",\n";
+  raw_result += "  \"owner_id\": \"9ea98bda-0935-40fc-b2c1-280e14757c64\",\n";
+  raw_result +=
+      "  \"owner_string\": "
+      "\"9ea98bda-0935-40fc-b2c1-210e14757c64@clients.auth.globus.org\",\n";
+  raw_result += "  \"preferred_concurrency\": null,\n";
+  raw_result += "  \"preferred_parallelism\": null,\n";
+  raw_result += "  \"public\": true,\n";
+  raw_result += "  \"requester_pays\": false,\n";
+  raw_result += "  \"s3_owner_activated\": false,\n";
+  raw_result += "  \"s3_url\": null,\n";
+  raw_result += "  \"shareable\": false,\n";
+  raw_result += "  \"sharing_target_endpoint\": "
+                "\"u_t2uyxw0jgkapzmwbfahbi5l4mq#3b3f5c6c-5b6a-11eb-87bf-"
+                "02187389bd35\",\n";
+  raw_result += "  \"sharing_target_root_path\": null,\n";
+  raw_result += "  \"storage_type\": null,\n";
+  raw_result +=
+      "  \"subscription_id\": \"3ba26681-e247-11e6-9d43-22000a1e3b52\",\n";
+  raw_result += "  \"tlsftp_server\": "
+                "\"tlsftp://g-f09277.e778b.bd7c.data.globus.org:443\",\n";
+  raw_result += "  \"user_message\": null,\n";
+  raw_result += "  \"user_message_link\": null,\n";
+  raw_result += "  \"username\": \"u_t2uyxwqjgvapzmwbfbhbi5l4mq\"\n";
+  raw_result += "}";
+
+  std::cout << "raw result" << std::endl;
+  // std::cout << raw_result << std::endl;
+  SDMS::global_logger.setSysLog(false);
+  SDMS::global_logger.addStream(std::cerr);
+  SDMS::global_logger.setLevel(SDMS::LogLevel::DEBUG);
+  SDMS::LogContext log_context;
+  DL_DEBUG(log_context, raw_result);
+
+  libjson::Value result;
+  result.fromString(raw_result);
+  std::cout << "Type of value: " << result.getTypeString() << std::endl;
+  libjson::Value::Object &resp_obj = result.asObject();
+
+  libjson::Value::Array &data = resp_obj.getArray("DATA");
+
+  BOOST_CHECK(data.size() == 0);
+}
+
+BOOST_AUTO_TEST_SUITE_END()