Tuesday, December 20, 2016

C++ Unit Test Framework Catch


1. class comparison in REQUIRE need operator == and  toString/template specialization/insertion operator
2. CATCH_TRANSLATE_EXCEPTION customize ex.message

 #define CATCH_CONFIG_MAIN  in stdafx.h

#include "stdafx.h"
#include "c:\__tools\catch.hpp"
#include <ostream>
#include <exception>

 class Book
{
public:
 int Id;
 bool operator==(const Book& b)
 {
  return b.Id == Id;
 }

};

//std::ostream& operator<<(std::ostream& os, Book const& b)
// {
// os << "overloading OS";
// return os;
//};
namespace Catch {
 template<> struct StringMaker<Book> {
  static std::string convert(Book const& value)
  {
   return "String Maker Specialization";
  }
 };

 //std::string toString(Book const& i)
 //{
 // return "to string for Book";
 //}
}
class myException : public std::exception
{
public:
 virtual const char* what() const throw()
 {
  return " my exception";
 }
};

CATCH_TRANSLATE_EXCEPTION(myException& ex)
{
 return ex.what();
}

TEST_CASE("This is a catch test","[Equal][LOG]")
{
 Book b1, b2;
 b1.Id = 90;
 INFO("Start Testing");
 REQUIRE(b1 == b2);
 WARN("One assertion failed");
 REQUIRE_FALSE(1 == 1);

}

TEST_CASE("This is another catch test","[CHK][EXP]")
{
 CHECK_FALSE(1 == 1);
 throw myException();
}



Saturday, December 10, 2016

Compile Time Check IsNullable and IsReferenceType


        public TimeSpan i { get; set; }
        public TimeSpan? j { get; set; }
        public string k { get; set; }
        public Status? Status { get; set; }
        public Data st1 { get; set; }
        public Data? st2 { get; set; }

        private void button_Click(object sender, RoutedEventArgs e)
        {
            
            bool b1 = IsNullable(i);
            bool b2 = IsNullable(j);
            bool b3 = IsNullable(k);
            bool b4 = IsNullable(Status);
            bool b5 = IsNullable(st1);
            bool b6 = IsNullable(st2);
            bool b7 = IsReferenceType(k);
        }
         static bool IsNullable<T>(T t) { return false; }
         static bool IsNullable<T>(T? t) where T : struct { return true; }
         static bool IsReferenceType<T>(T t) where T : class { return true; }
    

    public enum Status
    {
        None,
        Ok,
        Error
    }

    public struct Data
    {

    }

Thursday, December 8, 2016

Shift Operator, ilog2 and test power of 2

(1) shift left of 1 generate all powers of 2.
(2) ilog2 is template specialization.
(3) shift 1 by ilog2(n) will get back n for power of 2 only
(4) compiler say too complex when using recursion for non-template function is_power_of_2

#include "stdafx.h"
#include <iostream>

using namespace std;

template <size_t X>
struct ilog2
{
 enum {value=(1+ilog2<X/2>::value) };
};

template<>
struct ilog2<1> {enum {value=0}; };

template<size_t N>
bool is_pow_of_2()
{
 return ((size_t)1 << ilog2<N>::value == N);
};

int main() {
 
 cout << (1 << 3) << endl; // 8
 cout << (1 << 9) << endl; // 512=2 power 9
 
 cout << ((size_t)1 << ilog2<9>::value == 9) << endl;
 cout << ((size_t)1 << ilog2<512>::value == 512) << endl;
 
 cout << is_pow_of_2<9>() << endl;
 cout << is_pow_of_2<512>() << endl;
 return 0;
}



Wednesday, December 7, 2016

locking, lock free and wait free

locking --- lock_guard + mutex
lock free --- atomic + CAS
wait free --- atomic +fetch_add
ring buffer-- producer makes progress without any wait, so wait-free.


using namespace std;
typedef unsigned long ulong;

ulong _shared = 123UL;
int main() {
 {
  ulong* p=nullptr;  //locking
  *p = _shared;
  mutex M;
  {
   lock_guard<mutex> l(M);
   ++(*p);
  }
 }
 atomic<ulong>* p=0;  //lock free
 *p = _shared;
 ulong xl = p->load(memory_order_relaxed);
 while (!p->compare_exchange_strong(xl, xl + 1, std::memory_order_relaxed)) {}

 p->fetch_add(1, memory_order_relaxed);  //wait free


 // cache line is 64 bytes, ul is 8 bytes, so thread>8=> sit on separate cache line, no sharing faster.

 

 return 0;
}

lock_guard vs shared_lock is exclusive vs. shared in c++14

(1) C++ 14/17 rare write mostly read is Microsoft  ReaderWriter Lock concept.
(2) lock_guard also aware of how many shared lock in effect before exclude locking so some overhead.
(3) shared_lock can try timed 1 ms to see if writing in progress and give up
(4) both lock_guard and shared_lock construct on the same shared_timed_mutex


std::map<std::string, std::string> _map;
std::shared_timed_mutex m;

std::string find_entry(std::string s)
{
 std::shared_lock<std::shared_timed_mutex> guard(m);
 auto it = _map.find(s);
 if (it == _map.end())
 {
  throw runtime_error("not found");
 }
 return it->second;
}
void add_entry(std::string key,::string s)
{
 std::lock_guard<std::shared_timed_mutex> guard(m);
 _map.insert(make_pair(key,s));
}

void do_work_if_get_lock_in_1sec()
{
 shared_lock<shared_timed_mutex> sl(m, std::chrono::seconds(1));
 if (!sl.owns_lock())
  return;
 //do work after getting lock
}

Saturday, December 3, 2016

JSON Tester


#include "stdafx.h"
#include <iostream>
#include "JSONWrapper.hpp"
#include "render.hpp"

using namespace std;

int main() {

 JSONWrapper jw, jw1, jw2;
 //jw.value = true;
 //jw.value = 123.45;
 //jw.value = std::string{ "test" };
 //jw.value = nullptr;

 
 jw1.value = 678.90;
 jw2.value = true;

 JSONArray a{ jw1,jw2 };
 JSONArray b{ jw1,jw2 };
 //jw.value = a;

 JSONObject obj;
 obj.insert(std::pair<string, JSONArray>("k1", a));
 obj["k2"] = b;
 jw.value = obj;
 
 cout << render_json_value(jw.value) << endl;

 return 0;
}



fold.cpp recursion with compile time constant

(1) boost variant size =20, JSONValue variant=6
(2) v.which() = index
(3) using =typedef and decltype is to get typeinfo
(4) (n,N) recursion, Compile constant N=0, N+1 force n recurs 1 more time to get to n=N  
(5) have not see example Max,Max get called

#pragma once
#include <string>
#include <boost\variant.hpp>
#include "render.hpp"
#include "get2.hpp"

using namespace std;

template<size_t N, size_t Max>
struct apply_at
{
 template<typename R, typename T, typename F, typename...Fs>
 static string apply(T&& t, size_t n, F&& f, Fs&&... fs)
 {
  if (n == N)
  {
    return forward<F>(f)(get2<N>(boost::forward<T>(t)));
  }
  else
  {
   return apply_at<N + 1, Max>::template apply<R, T, Fs...>(
    boost::forward<T>(t),
    n,
    forward<Fs>(fs)...);
  }
 }
};

template<size_t Max>
struct apply_at<Max, Max>
{
 template<typename R, typename T, typename...Fs>
 static string apply(T, size_t, Fs...)
 {
  return R();
 }
};

template<typename T,typename F, typename...Fs>
static string fold_at(T&& t, size_t n, F&& f, Fs&&... fs)
{
  using R = decltype(f(get2<0>(t)));
  return apply_at<0, sizeof...(Fs)+1>::template apply<R,T, F, Fs...>(
   boost::forward<T>(t),
   n,
   forward<F>(f),
   forward<Fs>(fs)...
   );
};

template <typename... Ts, typename... Fs>
string fold(const boost::variant<Ts...>& v, Fs&&... fs)
{
 // size boost::variant=60, JSONValue=6, so assert fail
 //static_assert(sizeof...(Ts) == sizeof...(Fs), "# of fun and variant not matching.");
 return fold_at(
  v, v.which(), forward<Fs>(fs)...
 );
};

6 function of JSON render matching 6 type in JSON variant


#pragma once
#include <string>
#include <sstream>
#include "JSONWrapper.hpp"
#include "join.hpp"
#include "fold.hpp"
#include <iomanip>

using namespace std;

string render_bool(bool b) { return b ? "true" : "false"; }
string render_double(double d) { return to_string(d); }
string render_null(nullptr_t) { return "null"; }
string render_string(const string& s)
{
 stringstream ss;
 ss << std::quoted(s);
 return ss.str();
}

string render_json_value(const JSONValue& jsv);

string render_object(const JSONObject& obj)
{
 return string{ "[" }+
  join(obj.begin(), obj.end(), string{ "." },
   [](const JSONObject::value_type& jsv) {
  return render_string(jsv.first) + ":" + render_json_value(jsv.second);
 }) + "]";
}

string render_array(const JSONArray& a)
{
 return string{ "[" }+
  join(a.begin(), a.end(), string{ "," },
   [](const JSONValue& jsv) {
  return render_json_value(jsv);
 }) + "]";
}

string render_json_value(const JSONValue& jsv)
{
 return fold(jsv,
  render_bool, render_double, render_string,
  render_null, render_array, render_object);
}

join.cpp on iterator though vector and map


#pragma once
#include "JSONWrapper.hpp"
#include <functional>

#include <string>

using namespace std;

string join(JSONObject::const_iterator first, JSONObject::const_iterator last, string delimitor,
 std::function<string(const JSONObject::value_type&)> func)
{
 string ret = "";
 for (;first!= last; first++)
 {
  ret += func(*first) + delimitor;
 }
 return ret;
}

string join(JSONArray::const_iterator first, JSONArray::const_iterator last, string delimitor,
 std::function<string(const JSONValue&)> func)
{
 string ret = "";
 for (;first!= last; first++)
 {
  ret += func(*first) + delimitor;
 }
 return ret;
}


Friday, December 2, 2016

get boost variant value using template specialization on literal value

It seems C++17 will have get<0> and get<N> but boost does not have that yet.
boost only have get<type> and which=0,1,2,3,4,5
The following specialization can hack get<N> for now

#pragma once
#include <boost\variant\get.hpp>
#include "JSONWrapper.hpp"
#include <string>

template<int N>
auto get2(JSONValue jsv);

template<>
auto get2<0>(JSONValue jsv)
{
 return boost::get<bool>(jsv);
}

template<>
auto get2<1>(JSONValue jsv)
{
 return boost::get<double>(jsv);
}

template<>
auto get2<2>(JSONValue jsv)
{
 return boost::get<std::string>(jsv);
}

template<>
auto get2<3>(JSONValue jsv)
{
 return boost::get<nullptr_t>(jsv);
}

template<>
auto get2<4>(JSONValue jsv)
{
 return boost::get<JSONArray>(jsv);
}

template<>
auto get2<5>(JSONValue jsv)
{
 return boost::get<JSONObject>(jsv);
}

boost variant defines JSON Wrapper


Note operator JSONValue&() const meant  jw.operator const JSONValue&() the same as jw as in
cout<<render_json_value(jw)<<endl;

#include <vector>
#include <map>
#include <boost\variant.hpp>

typedef decltype(nullptr) nullptr_t;
struct JSONWrapper;
using JSONArray = std::vector<JSONWrapper>;
typedef std::map<std::string, JSONArray> JSONObject;
using JSONValue = boost::variant<bool, double, std::string, nullptr_t, JSONArray, JSONObject>;

struct JSONWrapper {
 JSONValue value;
 operator JSONValue&() { return value; }
 operator const JSONValue&() const { return value; }
};