Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/simpleini.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorunknown <brofield@users.noreply.github.com>2020-06-16 17:18:26 +0300
committerunknown <brofield@users.noreply.github.com>2020-06-16 17:18:26 +0300
commit3fea945de7264e7a6ae058211203a7f2b1a42b9d (patch)
tree3dd6c47deab24b62e7446486756c56a928b322a8 /tests
parentfe082fa81f4a55ddceb55056622136be616b3c6f (diff)
First stage of updating the project to have full test harness and incorporate some of the requested changes
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/example.ini2
-rw-r--r--tests/old/test.cmd24
-rw-r--r--tests/old/test1-expected.ini85
-rw-r--r--tests/old/test1-input.ini76
-rw-r--r--tests/old/test1.cpp166
-rw-r--r--tests/old/testsi-EUCJP.ini52
-rw-r--r--tests/old/testsi-SJIS.ini51
-rw-r--r--tests/old/testsi-UTF8.ini50
-rw-r--r--tests/old/testsi.cpp315
-rw-r--r--tests/packages.config4
-rw-r--r--tests/pch.cpp6
-rw-r--r--tests/pch.h8
-rw-r--r--tests/tests.ini13
-rw-r--r--tests/tests.vcxproj129
-rw-r--r--tests/ts-roundtrip.cpp163
-rw-r--r--tests/ts-snippets.cpp259
-rw-r--r--tests/ts-utf8.cpp67
-rw-r--r--tests/ts-wchar.cpp67
19 files changed, 1538 insertions, 0 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 0000000..51ade18
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1 @@
+example2.ini
diff --git a/tests/example.ini b/tests/example.ini
new file mode 100644
index 0000000..43b252c
--- /dev/null
+++ b/tests/example.ini
@@ -0,0 +1,2 @@
+[section]
+key = value
diff --git a/tests/old/test.cmd b/tests/old/test.cmd
new file mode 100644
index 0000000..2d319d5
--- /dev/null
+++ b/tests/old/test.cmd
@@ -0,0 +1,24 @@
+@echo off
+
+Debug\testsi.exe -u -m -l test1-input.ini > test1-blah.ini
+fc test1-expected.ini test1-output.ini
+if errorlevel 1 goto error
+
+"Debug Unicode\testsi.exe" -u -m -l test1-input.ini > test1-blah.ini
+fc test1-expected.ini test1-output.ini
+if errorlevel 1 goto error
+
+Release\testsi.exe -u -m -l test1-input.ini > test1-blah.ini
+fc test1-expected.ini test1-output.ini
+if errorlevel 1 goto error
+
+"Release Unicode\testsi.exe" -u -m -l test1-input.ini > test1-blah.ini
+fc test1-expected.ini test1-output.ini
+if errorlevel 1 goto error
+
+exit /b 0
+
+:error
+echo Failed during test run. Output file doesn't match expected file.
+pause
+exit /b 1
diff --git a/tests/old/test1-expected.ini b/tests/old/test1-expected.ini
new file mode 100644
index 0000000..dde335d
--- /dev/null
+++ b/tests/old/test1-expected.ini
@@ -0,0 +1,85 @@
+; testsi-UTF8-std.ini : standard UTF-8 test file for SimpleIni automated testing
+;
+; The number after a section or key is the order that it is defined in this file
+; to make it easier to see if it has been written out correctly. This file should
+; be loaded with Unicode / MultiKey / MultiLine turned on.
+
+
+
+; This comment should be joined on to the one below it about the key
+; with no section.
+
+; Key with no section
+lonely-key = nosection
+another = nosection either
+
+; This key has no value
+empty =
+
+
+; This should be joined with the comment below about japanese.
+; Another line which will be un-indented.
+
+; This is a section of keys showing the word Japanese in different syllabies.
+[ordered-1]
+a-1 = blah
+
+; this is in kanji
+japanese-2 = 日本語
+
+; this is in hiragana
+japanese-3 = にほんご
+
+; this is in katakana
+japanese-4 = ニホンゴ
+
+; this is in romaji
+japanese-5 = nihongo
+
+; kanji as the key
+日本語-6 = japanese
+
+
+[multi-2]
+
+; value a
+test = a
+
+; value b
+test = b
+
+; value c
+test = c
+
+; value d
+test = d
+
+
+[multiline-3]
+
+; This is obviously a multi-line entry
+multiline-1 = <<<END_OF_TEXT
+
+This is a multi-line comment. It
+will continue until we have the word MULTI
+on a line by itself.
+
+日本語も。
+
+END_OF_TEXT
+
+; This looks like multi-line, but because the newline following the last
+; line is discarded, it will be converted into a single line entry.
+another-2 = This is not a multiline entry.
+
+; If you wanted a multiline entry with a single line, you need to add
+; an extra line to it.
+another-3 = <<<END_OF_TEXT
+This is a multiline entry.
+
+END_OF_TEXT
+
+
+[integer]
+dec = 42
+hex = 0x2a
diff --git a/tests/old/test1-input.ini b/tests/old/test1-input.ini
new file mode 100644
index 0000000..6d27681
--- /dev/null
+++ b/tests/old/test1-input.ini
@@ -0,0 +1,76 @@
+; testsi-UTF8-std.ini : standard UTF-8 test file for SimpleIni automated testing
+;
+; The number after a section or key is the order that it is defined in this file
+; to make it easier to see if it has been written out correctly. This file should
+; be loaded with Unicode / MultiKey / MultiLine turned on.
+
+; This comment should be joined on to the one below it about the key
+; with no section.
+
+; Key with no section
+lonely-key = nosection
+another = nosection either
+
+; This key has no value
+empty =
+
+; This should be joined with the comment below about japanese.
+ ; Another line which will be un-indented.
+
+; This is a section of keys showing the word Japanese in different syllabies.
+[ordered-1]
+a-1 = blah
+
+; this is in kanji
+japanese-2 = 日本語
+
+; this is in hiragana
+japanese-3 = にほんご
+
+; this is in katakana
+japanese-4 = ニホンゴ
+
+; this is in romaji
+japanese-5 = nihongo
+
+; kanji as the key
+日本語-6 = japanese
+
+[multi-2]
+; value a
+test = a
+; value b
+test = b
+; value c
+test = c
+; value d
+test = d
+
+[multiline-3]
+; This is obviously a multi-line entry
+multiline-1 = <<<MULTI
+
+This is a multi-line comment. It
+will continue until we have the word MULTI
+on a line by itself.
+
+日本語も。
+
+MULTI
+
+; This looks like multi-line, but because the newline following the last
+; line is discarded, it will be converted into a single line entry.
+another-2 = <<<MULTI
+This is not a multiline entry.
+MULTI
+
+; If you wanted a multiline entry with a single line, you need to add
+; an extra line to it.
+another-3 = <<<MULTI
+This is a multiline entry.
+
+MULTI
+
+[integer]
+dec = 42
+hex = 0x2a
diff --git a/tests/old/test1.cpp b/tests/old/test1.cpp
new file mode 100644
index 0000000..3dd7800
--- /dev/null
+++ b/tests/old/test1.cpp
@@ -0,0 +1,166 @@
+// File: test1.cpp
+// Library: SimpleIni
+// Author: Brodie Thiesfield <code@jellycan.com>
+// Source: http://code.jellycan.com/simpleini/
+//
+// Automated testing for SimpleIni streams
+
+#ifdef _WIN32
+# pragma warning(disable: 4786)
+#endif
+
+#ifdef _WIN32
+# include <windows.h>
+# define DELETE_FILE DeleteFileA
+#else
+# include <unistd.h>
+# define DELETE_FILE unlink
+#endif
+#include <fstream>
+
+#define SI_SUPPORT_IOSTREAMS
+#include "SimpleIni.h"
+
+class Test
+{
+ std::string m_strTest;
+
+public:
+ Test(const char * a_pszName)
+ : m_strTest(a_pszName)
+ {
+ printf("%s: test starting\n", m_strTest.c_str());
+ }
+
+ bool Success()
+ {
+ printf("%s: test succeeded\n", m_strTest.c_str());
+ return false;
+ }
+
+ bool Failure(const char * pszReason)
+ {
+ printf("%s: test FAILED (%s)\n", m_strTest.c_str(), pszReason);
+ return false;
+ }
+};
+
+bool FileComparisonTest(const char * a_pszFile1, const char * a_pszFile2) {
+ // ensure that the two files are the same
+ try {
+ std::string strFile1, strFile2;
+
+ char szBuf[1024];
+ FILE * fp = NULL;
+
+#if __STDC_WANT_SECURE_LIB__
+ fopen_s(&fp, a_pszFile1, "rb");
+#else
+ fp = fopen(a_pszFile1, "rb");
+#endif
+ if (!fp) throw false;
+ while (!feof(fp)) {
+ size_t n = fread(szBuf, 1, sizeof(szBuf), fp);
+ strFile1.append(szBuf, n);
+ }
+ fclose(fp);
+
+ fp = NULL;
+#if __STDC_WANT_SECURE_LIB__
+ fopen_s(&fp, a_pszFile2, "rb");
+#else
+ fp = fopen(a_pszFile2, "rb");
+#endif
+ if (!fp) throw false;
+ while (!feof(fp)) {
+ size_t n = fread(szBuf, 1, sizeof(szBuf), fp);
+ strFile2.append(szBuf, n);
+ }
+ fclose(fp);
+
+ if (strFile1 != strFile2) throw false;
+ }
+ catch (...) {
+ return false;
+ }
+
+ return true;
+}
+
+bool FileLoadTest(const char * a_pszFile1, const char * a_pszFile2) {
+ // ensure that the two files load into simpleini the same
+ CSimpleIniA ini(true, true, true);
+ bool b;
+ try {
+ ini.Reset();
+ if (ini.LoadFile(a_pszFile1) < 0) throw "Load failed for file 1";
+ if (ini.SaveFile("test1.ini") < 0) throw "Save failed for file 1";
+
+ ini.Reset();
+ if (ini.LoadFile(a_pszFile2) < 0) throw "Load failed for file 2";
+ if (ini.SaveFile("test2.ini") < 0) throw "Save failed for file 2";
+
+ b = FileComparisonTest("test1.ini", "test2.ini");
+ DELETE_FILE("test1.ini");
+ DELETE_FILE("test2.ini");
+ if (!b) throw "File comparison failed in FileLoadTest";
+ }
+ catch (...) {
+ return false;
+ }
+
+ return true;
+}
+
+bool TestStreams()
+{
+ const char * rgszTestFile[3] = {
+ "test1-input.ini",
+ "test1-output.ini",
+ "test1-expected.ini"
+ };
+
+ Test oTest("TestStreams");
+
+ CSimpleIniW ini;
+ ini.SetUnicode(true);
+ ini.SetMultiKey(true);
+ ini.SetMultiLine(true);
+
+ // load the file
+ try {
+ std::ifstream instream;
+ instream.open(rgszTestFile[0], std::ifstream::in | std::ifstream::binary);
+ if (ini.LoadData(instream) < 0) throw false;
+ instream.close();
+ }
+ catch (...) {
+ return oTest.Failure("Failed to load file");
+ }
+
+ // standard contents test
+ //if (!StandardContentsTest(ini, oTest)) {
+ // return false;
+ //}
+
+ // save the file
+ try {
+ std::ofstream outfile;
+ outfile.open(rgszTestFile[1], std::ofstream::out | std::ofstream::binary);
+ if (ini.Save(outfile, true) < 0) throw false;
+ outfile.close();
+ }
+ catch (...) {
+ return oTest.Failure("Failed to save file");
+ }
+
+ // file comparison test
+ if (!FileComparisonTest(rgszTestFile[1], rgszTestFile[2])) {
+ return oTest.Failure("Failed file comparison");
+ }
+ if (!FileLoadTest(rgszTestFile[1], rgszTestFile[2])) {
+ return oTest.Failure("Failed file load comparison");
+ }
+
+ return oTest.Success();
+}
diff --git a/tests/old/testsi-EUCJP.ini b/tests/old/testsi-EUCJP.ini
new file mode 100644
index 0000000..16d1d06
--- /dev/null
+++ b/tests/old/testsi-EUCJP.ini
@@ -0,0 +1,52 @@
+; test file for SimpleIni
+
+nosection=ok
+NOSECTION=still ok
+ whitespace = ok
+
+[standard]
+foo=foo1
+standard-1=foo
+ܸ=ok1
+
+[Standard]
+Foo=foo2
+standard-2=foo
+ܸ=ok2
+
+ [ Whitespace ]
+
+a=
+
+[ whitespace in section name ]
+ whitespace in key name = whitespace in value name
+
+; comments
+ ; more comments
+
+invalid
+=invalid
+====invalid
+
+[Japanese]
+nihongo = ܸ
+ܸ = ܸ
+
+[ܸ]
+nihongo = ܸ
+ܸ = ܸ
+
+[]
+more=no section name
+
+
+
+[MultiLine]
+single = This is a single line.
+multi = <<<MULTI
+
+This is a multi-line value. It continues until the MULTI tag is found
+on a line by itself with no whitespace before or after it. This value
+will be returned to the user with all newlines and whitespace.
+
+MULTI
diff --git a/tests/old/testsi-SJIS.ini b/tests/old/testsi-SJIS.ini
new file mode 100644
index 0000000..585af09
--- /dev/null
+++ b/tests/old/testsi-SJIS.ini
@@ -0,0 +1,51 @@
+; test file for SimpleIni
+
+nosection=ok
+NOSECTION=still ok
+ whitespace = ok
+
+[standard]
+foo=foo1
+standard-1=foo
+{=ok1
+
+[Standard]
+Foo=foo2
+standard-2=foo
+{=ok2
+
+ [ Whitespace ]
+
+a=
+
+[ whitespace in section name ]
+ whitespace in key name = whitespace in value name
+
+; comments
+ ; more comments
+
+invalid
+=invalid
+====invalid
+
+[Japanese]
+nihongo = {
+{ = {
+
+[{]
+nihongo = {
+{ = {
+
+[]
+more=no section name
+
+
+[MultiLine]
+single = This is a single line.
+multi = <<<MULTI
+
+This is a multi-line value. It continues until the MULTI tag is found
+on a line by itself with no whitespace before or after it. This value
+will be returned to the user with all newlines and whitespace.
+
+MULTI
diff --git a/tests/old/testsi-UTF8.ini b/tests/old/testsi-UTF8.ini
new file mode 100644
index 0000000..ead2c40
--- /dev/null
+++ b/tests/old/testsi-UTF8.ini
@@ -0,0 +1,50 @@
+; test file for SimpleIni
+
+ whitespace = ok
+nosection=ok
+NOSECTION=still ok
+
+[standard]
+foo=foo1
+standard-1=foo
+日本語=ok1
+
+[Standard]
+Foo=foo2
+standard-2=foo
+日本語=ok2
+
+ [ Whitespace ]
+
+a=
+
+[ whitespace in section name ]
+ whitespace in key name = whitespace in value name
+
+; comments
+ ; more comments
+
+invalid
+=invalid
+====invalid
+
+[Japanese]
+nihongo = 日本語
+日本語 = 日本語
+
+[日本語]
+nihongo = 日本語
+日本語 = 日本語
+
+[]
+more=no section name
+
+[MultiLine]
+single = This is a single line.
+multi = <<<MULTI
+
+This is a multi-line value. It continues until the MULTI tag is found
+on a line by itself with no whitespace before or after it. This value
+will be returned to the user with all newlines and whitespace.
+
+MULTI
diff --git a/tests/old/testsi.cpp b/tests/old/testsi.cpp
new file mode 100644
index 0000000..0c5d7d7
--- /dev/null
+++ b/tests/old/testsi.cpp
@@ -0,0 +1,315 @@
+// File: testsi.cpp
+// Library: SimpleIni
+// Author: Brodie Thiesfield <code@jellycan.com>
+// Source: http://code.jellycan.com/simpleini/
+//
+// Demo of usage
+
+#ifdef _WIN32
+# pragma warning(disable: 4786)
+#endif
+
+#include <locale.h>
+#include <stdio.h>
+#include <cassert>
+
+#define SI_SUPPORT_IOSTREAMS
+#if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE)
+# include <fstream>
+#endif
+
+//#define SI_CONVERT_GENERIC
+//#define SI_CONVERT_ICU
+//#define SI_CONVERT_WIN32
+#include "../SimpleIni.h"
+
+#ifdef SI_CONVERT_ICU
+// if converting using ICU then we need the ICU library
+# pragma comment(lib, "icuuc.lib")
+#endif
+
+#ifdef _WIN32
+# include <tchar.h>
+#else // !_WIN32
+# define TCHAR char
+# define _T(x) x
+# define _tprintf printf
+# define _tmain main
+#endif // _WIN32
+
+static void
+Test(
+ CSimpleIni & ini
+ )
+{
+ const TCHAR *pszSection = 0;
+ const TCHAR *pItem = 0;
+ const TCHAR *pszVal = 0;
+
+ // get the value of the key "foo" in section "standard"
+ bool bHasMulti;
+ pszVal = ini.GetValue(_T("standard"), _T("foo"), 0, &bHasMulti);
+ _tprintf(_T("\n-- Value of standard::foo is '%s' (hasMulti = %d)\n"),
+ pszVal ? pszVal : _T("(null)"), bHasMulti);
+
+ // set the value of the key "foo" in section "standard"
+ ini.SetValue(_T("standard"), _T("foo"), _T("wibble"));
+ pszVal = ini.GetValue(_T("standard"), _T("foo"), 0, &bHasMulti);
+ _tprintf(_T("\n-- Value of standard::foo is '%s' (hasMulti = %d)\n"),
+ pszVal ? pszVal : _T("(null)"), bHasMulti);
+
+ // get all values of the key "foo" in section "standard"
+ CSimpleIni::TNamesDepend values;
+ if (ini.GetAllValues(_T("standard"), _T("foo"), values)) {
+ _tprintf(_T("\n-- Values of standard::foo are:\n"));
+ CSimpleIni::TNamesDepend::const_iterator i = values.begin();
+ for (; i != values.end(); ++i) {
+ pszVal = i->pItem;
+ _tprintf(_T(" -> '%s'\n"), pszVal);
+ }
+ }
+
+ // get the size of the section [standard]
+ _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"),
+ ini.GetSectionSize(_T("standard")));
+
+ // delete the key "foo" in section "standard", if it has value "bar"
+ ini.DeleteValue(_T("standard"), _T("foo"), _T("bar"));
+ pszVal = ini.GetValue(_T("standard"), _T("foo"), 0);
+ _tprintf(_T("\n-- Value of standard::foo is now '%s'\n"),
+ pszVal ? pszVal : _T("(null)"));
+
+ // delete the key "foo" in section "standard"
+ ini.Delete(_T("standard"), _T("foo"));
+ pszVal = ini.GetValue(_T("standard"), _T("foo"), 0);
+ _tprintf(_T("\n-- Value of standard::foo is now '%s'\n"),
+ pszVal ? pszVal : _T("(null)"));
+
+ // get the size of the section [standard]
+ _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"),
+ ini.GetSectionSize(_T("standard")));
+
+ // get the list of all key names for the section "standard"
+ _tprintf(_T("\n-- Dumping keys of section: [standard]\n"));
+ CSimpleIni::TNamesDepend keys;
+ ini.GetAllKeys(_T("standard"), keys);
+
+ // dump all of the key names
+ CSimpleIni::TNamesDepend::const_iterator iKey = keys.begin();
+ for ( ; iKey != keys.end(); ++iKey ) {
+ pItem = iKey->pItem;
+ _tprintf(_T("Key: %s\n"), pItem);
+ }
+
+ // add a decimal value
+ ini.SetLongValue(_T("integer"), _T("dec"), 42, NULL, false);
+ ini.SetLongValue(_T("integer"), _T("hex"), 42, NULL, true);
+
+ // add some bool values
+ ini.SetBoolValue(_T("bool"), _T("t"), true);
+ ini.SetBoolValue(_T("bool"), _T("f"), false);
+
+ // get the values back
+ assert(42 == ini.GetLongValue(_T("integer"), _T("dec")));
+ assert(42 == ini.GetLongValue(_T("integer"), _T("hex")));
+ assert(true == ini.GetBoolValue(_T("bool"), _T("t")));
+ assert(false == ini.GetBoolValue(_T("bool"), _T("f")));
+
+ // delete the section "standard"
+ ini.Delete(_T("standard"), NULL);
+ _tprintf(_T("\n-- Number of keys in section [standard] = %d\n"),
+ ini.GetSectionSize(_T("standard")));
+
+ // iterate through every section in the file
+ _tprintf(_T("\n-- Dumping all sections\n"));
+ CSimpleIni::TNamesDepend sections;
+ ini.GetAllSections(sections);
+ CSimpleIni::TNamesDepend::const_iterator iSection = sections.begin();
+ for ( ; iSection != sections.end(); ++iSection ) {
+ pszSection = iSection->pItem;
+
+ // print the section name
+ printf("\n");
+ if (*pszSection) {
+ _tprintf(_T("[%s]\n"), pszSection);
+ }
+
+ // if there are keys and values...
+ const CSimpleIni::TKeyVal * pSectionData = ini.GetSection(pszSection);
+ if (pSectionData) {
+ // iterate over all keys and dump the key name and value
+ CSimpleIni::TKeyVal::const_iterator iKeyVal = pSectionData->begin();
+ for ( ;iKeyVal != pSectionData->end(); ++iKeyVal) {
+ pItem = iKeyVal->first.pItem;
+ pszVal = iKeyVal->second;
+ _tprintf(_T("%s=%s\n"), pItem, pszVal);
+ }
+ }
+ }
+}
+
+#if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE)
+static bool
+TestStreams(
+ const TCHAR * a_pszFile,
+ bool a_bIsUtf8,
+ bool a_bUseMultiKey,
+ bool a_bUseMultiLine
+ )
+{
+ // load the file
+ CSimpleIni ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine);
+ _tprintf(_T("Loading file: %s\n"), a_pszFile);
+ std::ifstream instream;
+ instream.open(a_pszFile, std::ifstream::in | std::ifstream::binary);
+ SI_Error rc = ini.LoadData(instream);
+ instream.close();
+ if (rc < 0) {
+ printf("Failed to open file.\n");
+ return false;
+ }
+
+ Test(ini);
+
+ // save the file (simple)
+ _tprintf(_T("\n-- Saving file to: testsi-out-streams.ini\n"));
+ std::ofstream outstream;
+ outstream.open("testsi-out-streams.ini", std::ofstream::out | std::ofstream::binary);
+ ini.Save(outstream);
+ outstream.close();
+
+ return true;
+}
+#endif // SI_SUPPORT_IOSTREAMS
+
+static bool
+TestFile(
+ const TCHAR * a_pszFile,
+ bool a_bIsUtf8,
+ bool a_bUseMultiKey,
+ bool a_bUseMultiLine
+ )
+{
+ // load the file
+ CSimpleIni ini(a_bIsUtf8, a_bUseMultiKey, a_bUseMultiLine);
+ _tprintf(_T("Loading file: %s\n"), a_pszFile);
+ SI_Error rc = ini.LoadFile(a_pszFile);
+ if (rc < 0) {
+ printf("Failed to open file.\n");
+ return false;
+ }
+
+ // run the tests
+ Test(ini);
+
+ // save the file (simple)
+ _tprintf(_T("\n-- Saving file to: testsi-out.ini\n"));
+ ini.SaveFile("testsi-out.ini");
+
+ // save the file (with comments)
+ // Note: to save the file and add a comment to the beginning, use
+ // code such as the following.
+ _tprintf(_T("\n-- Saving file to: testsi-out-comment.ini\n"));
+ FILE * fp = NULL;
+#if __STDC_WANT_SECURE_LIB__
+ fopen_s(&fp, "testsi-out-comment.ini", "wb");
+#else
+ fp = fopen("testsi-out-comment.ini", "wb");
+#endif
+ if (fp) {
+ CSimpleIni::FileWriter writer(fp);
+ if (a_bIsUtf8) {
+ writer.Write(SI_UTF8_SIGNATURE);
+ }
+
+ // add a string to the file in the correct text format
+ CSimpleIni::Converter convert = ini.GetConverter();
+ convert.ConvertToStore(_T("; output from testsi.cpp test program")
+ SI_NEWLINE SI_NEWLINE);
+ writer.Write(convert.Data());
+
+ ini.Save(writer, false);
+ fclose(fp);
+ }
+
+ return true;
+}
+
+static bool
+ParseCommandLine(
+ int argc,
+ TCHAR * argv[],
+ const TCHAR * & a_pszFile,
+ bool & a_bIsUtf8,
+ bool & a_bUseMultiKey,
+ bool & a_bUseMultiLine
+ )
+{
+ a_pszFile = 0;
+ a_bIsUtf8 = false;
+ a_bUseMultiKey = false;
+ a_bUseMultiLine = false;
+ for (--argc; argc > 0; --argc) {
+ if (argv[argc][0] == '-') {
+ switch (argv[argc][1]) {
+ case TCHAR('u'):
+ a_bIsUtf8 = true;
+ break;
+ case TCHAR('m'):
+ a_bUseMultiKey = true;
+ break;
+ case TCHAR('l'):
+ a_bUseMultiLine = true;
+ break;
+ }
+ }
+ else {
+ a_pszFile = argv[argc];
+ }
+ }
+ if (!a_pszFile) {
+ _tprintf(
+ _T("Usage: testsi [-u] [-m] [-l] iniFile\n")
+ _T(" -u Load file as UTF-8 (Default is to use system locale)\n")
+ _T(" -m Enable multiple keys\n")
+ _T(" -l Enable multiple line values\n")
+ );
+ return false;
+ }
+
+ return true;
+}
+
+extern bool TestStreams();
+
+int
+_tmain(
+ int argc,
+ TCHAR * argv[]
+ )
+{
+ setlocale(LC_ALL, "");
+
+ // start of automated testing...
+ TestStreams();
+
+ // parse the command line
+ const TCHAR * pszFile;
+ bool bIsUtf8, bUseMultiKey, bUseMultiLine;
+ if (!ParseCommandLine(argc, argv, pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) {
+ return 1;
+ }
+
+ // run the test
+ if (!TestFile(pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) {
+ return 1;
+ }
+#if defined(SI_SUPPORT_IOSTREAMS) && !defined(_UNICODE)
+ if (!TestStreams(pszFile, bIsUtf8, bUseMultiKey, bUseMultiLine)) {
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
diff --git a/tests/packages.config b/tests/packages.config
new file mode 100644
index 0000000..6c6422e
--- /dev/null
+++ b/tests/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn" version="1.8.1.3" targetFramework="native" />
+</packages> \ No newline at end of file
diff --git a/tests/pch.cpp b/tests/pch.cpp
new file mode 100644
index 0000000..97b544e
--- /dev/null
+++ b/tests/pch.cpp
@@ -0,0 +1,6 @@
+//
+// pch.cpp
+// Include the standard header and generate the precompiled header.
+//
+
+#include "pch.h"
diff --git a/tests/pch.h b/tests/pch.h
new file mode 100644
index 0000000..29c81ff
--- /dev/null
+++ b/tests/pch.h
@@ -0,0 +1,8 @@
+//
+// pch.h
+// Header for standard system include files.
+//
+
+#pragma once
+
+#include "gtest/gtest.h"
diff --git a/tests/tests.ini b/tests/tests.ini
new file mode 100644
index 0000000..ea66f7a
--- /dev/null
+++ b/tests/tests.ini
@@ -0,0 +1,13 @@
+[section1]
+key1=value1
+
+[section2]
+test2=テスト2
+テスト=test
+テスト2=テスト二
+
+[検査]
+key2=value2
+test2=テスト2
+テスト=test
+テスト2=テスト二
diff --git a/tests/tests.vcxproj b/tests/tests.vcxproj
new file mode 100644
index 0000000..5fe1d76
--- /dev/null
+++ b/tests/tests.vcxproj
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{8f30a5dc-b942-4c9a-ba75-91c906ff85fa}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v142</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ <ProjectName>tests</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings" />
+ <ImportGroup Label="Shared" />
+ <ImportGroup Label="PropertySheets" />
+ <PropertyGroup Label="UserMacros" />
+ <ItemGroup>
+ <ClInclude Include="pch.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="ts-roundtrip.cpp" />
+ <ClCompile Include="ts-snippets.cpp" />
+ <ClCompile Include="ts-utf8.cpp" />
+ <ClCompile Include="pch.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="ts-wchar.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="example.ini" />
+ <None Include="packages.config" />
+ <None Include="tests.ini" />
+ </ItemGroup>
+ <ItemDefinitionGroup />
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ <Import Project="..\vcproj\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.3\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets" Condition="Exists('..\vcproj\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.3\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets')" />
+ </ImportGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Console</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ </Link>
+ </ItemDefinitionGroup>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\vcproj\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.3\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\vcproj\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.3\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets'))" />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/tests/ts-roundtrip.cpp b/tests/ts-roundtrip.cpp
new file mode 100644
index 0000000..3808a08
--- /dev/null
+++ b/tests/ts-roundtrip.cpp
@@ -0,0 +1,163 @@
+#include "pch.h"
+#include <algorithm>
+#include "../SimpleIni.h"
+
+class TestRoundTrip : public ::testing::Test {
+protected:
+ void TestRoundTrip::SetUp() override;
+ void TestMulti();
+ void TestBOM(bool useBOM);
+
+protected:
+ CSimpleIniA ini;
+ std::string input;
+ std::string output;
+};
+
+void TestRoundTrip::SetUp() {
+ ini.SetUnicode();
+}
+
+TEST_F(TestRoundTrip, TestStandard) {
+ input =
+ "; File comment\n"
+ "\n"
+ "\n"
+ "; Section 1 comment\n"
+ "[section1]\n"
+ "\n"
+ "\n"
+ "; Section 2 comment\n"
+ "[section2]\n"
+ "key1 = string\n"
+ "key2 = true\n"
+ "key3 = 3.1415\n"
+ ;
+
+ SI_Error rc = ini.LoadData(input);
+ ASSERT_EQ(rc, SI_OK);
+
+ const char* result = ini.GetValue("section2", "key1");
+ ASSERT_STREQ(result, "string");
+
+ rc = ini.Save(output);
+ ASSERT_EQ(rc, SI_OK);
+
+ output.erase(std::remove(output.begin(), output.end(), '\r'), output.end());
+ ASSERT_STREQ(input.c_str(), output.c_str());
+}
+
+void TestRoundTrip::TestMulti() {
+ input =
+ "[section]\n"
+ "key = string1\n"
+ "key = string2\n"
+ ;
+
+ SI_Error rc = ini.LoadData(input);
+ ASSERT_EQ(rc, SI_OK);
+
+ rc = ini.Save(output);
+ ASSERT_EQ(rc, SI_OK);
+
+ output.erase(std::remove(output.begin(), output.end(), '\r'), output.end());
+}
+
+TEST_F(TestRoundTrip, TestMultiGood) {
+ ini.SetMultiKey(true);
+ TestMulti();
+ ASSERT_STREQ(input.c_str(), output.c_str());
+}
+
+TEST_F(TestRoundTrip, TestMultiBad) {
+ std::string expected =
+ "[section]\n"
+ "key = string2\n";
+
+ ini.SetMultiKey(false);
+ TestMulti();
+ ASSERT_STRNE(input.c_str(), output.c_str());
+ ASSERT_STREQ(expected.c_str(), output.c_str());
+}
+
+TEST_F(TestRoundTrip, TestSpacesTrue) {
+ input =
+ "[section]\n"
+ "key = string1\n";
+
+ SI_Error rc = ini.LoadData(input);
+ ASSERT_EQ(rc, SI_OK);
+
+ ini.SetSpaces(true);
+ rc = ini.Save(output);
+ ASSERT_EQ(rc, SI_OK);
+
+ output.erase(std::remove(output.begin(), output.end(), '\r'), output.end());
+
+ ASSERT_STREQ(input.c_str(), output.c_str());
+}
+
+TEST_F(TestRoundTrip, TestSpacesFalse) {
+ input =
+ "[section]\n"
+ "key = string1\n";
+
+ SI_Error rc = ini.LoadData(input);
+ ASSERT_EQ(rc, SI_OK);
+
+ ini.SetSpaces(false);
+ rc = ini.Save(output);
+ ASSERT_EQ(rc, SI_OK);
+
+ output.erase(std::remove(output.begin(), output.end(), '\r'), output.end());
+
+ ASSERT_STRNE(input.c_str(), output.c_str());
+
+ std::string expected =
+ "[section]\n"
+ "key=string1\n";
+
+ ASSERT_STREQ(expected.c_str(), output.c_str());
+}
+
+void TestRoundTrip::TestBOM(bool useBOM) {
+ const char bom[] = "\xEF\xBB\xBF";
+ const char input8[] =
+ u8"[テスト1]\n"
+ u8"テスト2 = テスト3\n";
+
+ input = bom;
+ input += input8;
+
+ ini.Reset();
+ ini.SetUnicode(false);
+ SI_Error rc = ini.LoadData(input);
+ ASSERT_EQ(rc, SI_OK);
+
+ const char tesuto1[] = u8"テスト1";
+ const char tesuto2[] = u8"テスト2";
+ const char tesuto3[] = u8"テスト3";
+
+ const char* result = ini.GetValue(tesuto1, tesuto2);
+ ASSERT_STREQ(result, tesuto3);
+
+ rc = ini.Save(output, useBOM);
+ ASSERT_EQ(rc, SI_OK);
+
+ output.erase(std::remove(output.begin(), output.end(), '\r'), output.end());
+}
+
+TEST_F(TestRoundTrip, TestWithBOM) {
+ TestBOM(true);
+
+ ASSERT_STREQ(input.c_str(), output.c_str());
+}
+
+TEST_F(TestRoundTrip, TestWithoutBOM) {
+ TestBOM(false);
+
+ ASSERT_STRNE(input.c_str(), output.c_str());
+
+ std::string expected(input, 3);
+ ASSERT_STREQ(expected.c_str(), output.c_str());
+}
diff --git a/tests/ts-snippets.cpp b/tests/ts-snippets.cpp
new file mode 100644
index 0000000..d18150e
--- /dev/null
+++ b/tests/ts-snippets.cpp
@@ -0,0 +1,259 @@
+#include "pch.h"
+#include "../SimpleIni.h"
+
+
+// ### SIMPLE USAGE
+
+TEST(TestSnippets, TestSimple) {
+ // simple demonstration
+
+ CSimpleIniA ini;
+ ini.SetUnicode();
+
+ SI_Error rc = ini.LoadFile("example.ini");
+ if (rc < 0) { /* handle error */ };
+ ASSERT_EQ(rc, SI_OK);
+
+ const char* pv;
+ pv = ini.GetValue("section", "key", "default");
+ ASSERT_STREQ(pv, "value");
+
+ ini.SetValue("section", "key", "newvalue");
+
+ pv = ini.GetValue("section", "key", "default");
+ ASSERT_STREQ(pv, "newvalue");
+}
+
+
+// ### LOADING DATA
+
+TEST(TestSnippets, TestLoadFile) {
+ // load from a data file
+ CSimpleIniA ini;
+ SI_Error rc = ini.LoadFile("example.ini");
+ if (rc < 0) { /* handle error */ };
+ ASSERT_EQ(rc, SI_OK);
+}
+
+TEST(TestSnippets, TestLoadString) {
+ // load from a string
+ const std::string example = "[section]\nkey = value\n";
+ CSimpleIniA ini;
+ SI_Error rc = ini.LoadData(example);
+ if (rc < 0) { /* handle error */ };
+ ASSERT_EQ(rc, SI_OK);
+}
+
+
+// ### GETTING SECTIONS AND KEYS
+
+TEST(TestSnippets, TestSectionsAndKeys) {
+ const std::string example =
+ "[section1]\n"
+ "key1 = value1\n"
+ "key2 = value2\n"
+ "\n"
+ "[section2]\n"
+ "[section3]\n";
+
+ CSimpleIniA ini;
+ SI_Error rc = ini.LoadData(example);
+ ASSERT_EQ(rc, SI_OK);
+
+
+
+ // get all sections
+ CSimpleIniA::TNamesDepend sections;
+ ini.GetAllSections(sections);
+
+ // get all keys in a section
+ CSimpleIniA::TNamesDepend keys;
+ ini.GetAllKeys("section1", keys);
+
+
+
+ const char* expectedSections[] = { "section1", "section2", "section3", nullptr };
+ const char* expectedKeys[] = { "key1", "key2", nullptr };
+
+ CSimpleIniA::TNamesDepend::const_iterator it;
+ int i;
+
+ for (i = 0, it = sections.begin(); it != sections.end(); ++i, ++it) {
+ ASSERT_NE(expectedSections[i], nullptr);
+ ASSERT_STREQ(expectedSections[i], it->pItem);
+ }
+ ASSERT_EQ(expectedSections[i], nullptr);
+
+ for (i = 0, it = keys.begin(); it != keys.end(); ++i, ++it) {
+ ASSERT_NE(expectedKeys[i], nullptr);
+ ASSERT_STREQ(expectedKeys[i], it->pItem);
+ }
+ ASSERT_EQ(expectedKeys[i], nullptr);
+}
+
+
+// ### GETTING VALUES
+
+TEST(TestSnippets, TestGettingValues) {
+ const std::string example =
+ "[section1]\n"
+ "key1 = value1\n"
+ "key2 = value2.1\n"
+ "key2 = value2.2\n"
+ "\n"
+ "[section2]\n"
+ "[section3]\n";
+
+ bool utf8 = true;
+ bool multiKey = true;
+ CSimpleIniA ini(utf8, multiKey);
+ SI_Error rc = ini.LoadData(example);
+ ASSERT_EQ(rc, SI_OK);
+
+
+ // get the value of a key that doesn't exist
+ const char* pv;
+ pv = ini.GetValue("section1", "key99");
+ ASSERT_EQ(pv, nullptr);
+
+ // get the value of a key that does exist
+ pv = ini.GetValue("section1", "key1");
+ ASSERT_STREQ(pv, "value1");
+
+ // get the value of a key which may have multiple
+ // values. If hasMultiple is true, then there are
+ // multiple values and just one value has been returned
+ bool hasMulti;
+ pv = ini.GetValue("section1", "key1", nullptr, &hasMulti);
+ ASSERT_STREQ(pv, "value1");
+ ASSERT_EQ(hasMulti, false);
+
+ pv = ini.GetValue("section1", "key2", nullptr, &hasMulti);
+ ASSERT_STREQ(pv, "value2.1");
+ ASSERT_EQ(hasMulti, true);
+
+ // get all values of a key with multiple values
+ CSimpleIniA::TNamesDepend values;
+ ini.GetAllValues("section1", "key2", values);
+
+ // sort the values into a known order, in this case we want
+ // the original load order
+ values.sort(CSimpleIniA::Entry::LoadOrder());
+
+ // output all of the items
+ CSimpleIniA::TNamesDepend::const_iterator it;
+ for (it = values.begin(); it != values.end(); ++it) {
+ printf("value = '%s'\n", it->pItem);
+ }
+
+
+ int i;
+ const char* expectedValues[] = { "value2.1", "value2.2", nullptr };
+ for (i = 0, it = values.begin(); it != values.end(); ++it, ++i) {
+ ASSERT_NE(expectedValues[i], nullptr);
+ ASSERT_STREQ(expectedValues[i], it->pItem);
+ }
+ ASSERT_EQ(expectedValues[i], nullptr);
+}
+
+
+// ### MODIFYING DATA
+
+TEST(TestSnippets, TestModifyingData) {
+ bool utf8 = true;
+ bool multiKey = false;
+ CSimpleIniA ini(utf8, multiKey);
+ SI_Error rc;
+
+
+ // add a new section
+ rc = ini.SetValue("section1", nullptr, nullptr);
+ if (rc < 0) { /* handle error */ };
+ ASSERT_EQ(rc, SI_INSERTED);
+
+ // not an error to add one that already exists
+ rc = ini.SetValue("section1", nullptr, nullptr);
+ if (rc < 0) { /* handle error */ };
+ ASSERT_EQ(rc, SI_UPDATED);
+
+ // get the value of a key that doesn't exist
+ const char* pv;
+ pv = ini.GetValue("section2", "key1", "default-value");
+ ASSERT_STREQ(pv, "default-value");
+
+ // adding a key (the section will be added if needed)
+ rc = ini.SetValue("section2", "key1", "value1");
+ if (rc < 0) { /* handle error */ };
+ ASSERT_EQ(rc, SI_INSERTED);
+
+ // ensure it is set to expected value
+ pv = ini.GetValue("section2", "key1", nullptr);
+ ASSERT_STREQ(pv, "value1");
+
+ // change the value of a key
+ rc = ini.SetValue("section2", "key1", "value2");
+ if (rc < 0) { /* handle error */ };
+ ASSERT_EQ(rc, SI_UPDATED);
+
+ // ensure it is set to expected value
+ pv = ini.GetValue("section2", "key1", nullptr);
+ ASSERT_STREQ(pv, "value2");
+}
+
+
+// ### DELETING DATA
+
+TEST(TestSnippets, TestDeletingData) {
+ const std::string example =
+ "[section1]\n"
+ "key1 = value1\n"
+ "key2 = value2\n"
+ "\n"
+ "[section2]\n"
+ "key1 = value1\n"
+ "key2 = value2\n"
+ "\n"
+ "[section3]\n";
+
+ bool utf8 = true;
+ CSimpleIniA ini(utf8);
+ SI_Error rc = ini.LoadData(example);
+ ASSERT_EQ(rc, SI_OK);
+
+
+ // deleting a key from a section. Optionally the entire
+ // section may be deleted if it is now empty.
+ bool done, deleteSectionIfEmpty = true;
+ done = ini.Delete("section1", "key1", deleteSectionIfEmpty);
+ ASSERT_EQ(done, true);
+ done = ini.Delete("section1", "key1");
+ ASSERT_EQ(done, false);
+
+ // deleting an entire section and all keys in it
+ done = ini.Delete("section2", nullptr);
+ ASSERT_EQ(done, true);
+ done = ini.Delete("section2", nullptr);
+ ASSERT_EQ(done, false);
+}
+
+
+// ### SAVING DATA
+
+TEST(TestSnippets, TestSavingData) {
+ bool utf8 = true;
+ CSimpleIniA ini(utf8);
+ SI_Error rc;
+
+
+ // save the data to a string
+ std::string data;
+ rc = ini.Save(data);
+ if (rc < 0) { /* handle error */ };
+ ASSERT_EQ(rc, SI_OK);
+
+ // save the data back to the file
+ rc = ini.SaveFile("example2.ini");
+ if (rc < 0) { /* handle error */ };
+ ASSERT_EQ(rc, SI_OK);
+}
+
diff --git a/tests/ts-utf8.cpp b/tests/ts-utf8.cpp
new file mode 100644
index 0000000..9208648
--- /dev/null
+++ b/tests/ts-utf8.cpp
@@ -0,0 +1,67 @@
+#include "pch.h"
+#include "../SimpleIni.h"
+
+class TestUTF8 : public ::testing::Test {
+protected:
+ void TestUTF8::SetUp() override;
+protected:
+ CSimpleIniA ini;
+};
+
+void TestUTF8::SetUp() {
+ ini.SetUnicode();
+ SI_Error err = ini.LoadFile("tests.ini");
+ ASSERT_EQ(err, SI_OK);
+}
+
+TEST_F(TestUTF8, TestSectionAKeyAValA) {
+ const char* result = ini.GetValue("section1", "key1");
+ ASSERT_STREQ(result, "value1");
+}
+
+TEST_F(TestUTF8, TestSectionAKeyAValU) {
+ const char tesuto2[] = u8"テスト2";
+ const char* result = ini.GetValue("section2", "test2");
+ ASSERT_STREQ(result, tesuto2);
+}
+
+TEST_F(TestUTF8, TestSectionAKeyUValA) {
+ const char tesuto[] = u8"テスト";
+ const char* result = ini.GetValue("section2", tesuto);
+ ASSERT_STREQ(result, "test");
+}
+
+TEST_F(TestUTF8, TestSectionAKeyUValU) {
+ const char tesuto2[] = u8"テスト2";
+ const char tesutoni[] = u8"テスト二";
+ const char* result = ini.GetValue("section2", tesuto2);
+ ASSERT_STREQ(result, tesutoni);
+}
+
+TEST_F(TestUTF8, TestSectionUKeyAValA) {
+ const char kensa[] = u8"検査";
+ const char* result = ini.GetValue(kensa, "key2");
+ ASSERT_STREQ(result, "value2");
+}
+
+TEST_F(TestUTF8, TestSectionUKeyAValU) {
+ const char kensa[] = u8"検査";
+ const char tesuto2[] = u8"テスト2";
+ const char* result = ini.GetValue(kensa, "test2");
+ ASSERT_STREQ(result, tesuto2);
+}
+
+TEST_F(TestUTF8, TestSectionUKeyUValA) {
+ const char kensa[] = u8"検査";
+ const char tesuto[] = u8"テスト";
+ const char* result = ini.GetValue(kensa, tesuto);
+ ASSERT_STREQ(result, "test");
+}
+
+TEST_F(TestUTF8, TestSectionUKeyUValU) {
+ const char kensa[] = u8"検査";
+ const char tesuto2[] = u8"テスト2";
+ const char tesutoni[] = u8"テスト二";
+ const char* result = ini.GetValue(kensa, tesuto2);
+ ASSERT_STREQ(result, tesutoni);
+}
diff --git a/tests/ts-wchar.cpp b/tests/ts-wchar.cpp
new file mode 100644
index 0000000..8041272
--- /dev/null
+++ b/tests/ts-wchar.cpp
@@ -0,0 +1,67 @@
+#include "pch.h"
+#include "../SimpleIni.h"
+
+class TestWide : public ::testing::Test {
+protected:
+ void TestWide::SetUp() override;
+protected:
+ CSimpleIniW ini;
+};
+
+void TestWide::SetUp() {
+ ini.SetUnicode();
+ SI_Error err = ini.LoadFile(L"tests.ini");
+ ASSERT_EQ(err, SI_OK);
+}
+
+TEST_F(TestWide, TestSectionAKeyAValA) {
+ const wchar_t* result = ini.GetValue(L"section1", L"key1");
+ ASSERT_STREQ(result, L"value1");
+}
+
+TEST_F(TestWide, TestSectionAKeyAValU) {
+ const wchar_t tesuto2[] = L"テスト2";
+ const wchar_t* result = ini.GetValue(L"section2", L"test2");
+ ASSERT_STREQ(result, tesuto2);
+}
+
+TEST_F(TestWide, TestSectionAKeyUValA) {
+ const wchar_t tesuto[] = L"テスト";
+ const wchar_t* result = ini.GetValue(L"section2", tesuto);
+ ASSERT_STREQ(result, L"test");
+}
+
+TEST_F(TestWide, TestSectionAKeyUValU) {
+ const wchar_t tesuto2[] = L"テスト2";
+ const wchar_t tesutoni[] = L"テスト二";
+ const wchar_t* result = ini.GetValue(L"section2", tesuto2);
+ ASSERT_STREQ(result, tesutoni);
+}
+
+TEST_F(TestWide, TestSectionUKeyAValA) {
+ const wchar_t kensa[] = L"検査";
+ const wchar_t* result = ini.GetValue(kensa, L"key2");
+ ASSERT_STREQ(result, L"value2");
+}
+
+TEST_F(TestWide, TestSectionUKeyAValU) {
+ const wchar_t kensa[] = L"検査";
+ const wchar_t tesuto2[] = L"テスト2";
+ const wchar_t* result = ini.GetValue(kensa, L"test2");
+ ASSERT_STREQ(result, tesuto2);
+}
+
+TEST_F(TestWide, TestSectionUKeyUValA) {
+ const wchar_t kensa[] = L"検査";
+ const wchar_t tesuto[] = L"テスト";
+ const wchar_t* result = ini.GetValue(kensa, tesuto);
+ ASSERT_STREQ(result, L"test");
+}
+
+TEST_F(TestWide, TestSectionUKeyUValU) {
+ const wchar_t kensa[] = L"検査";
+ const wchar_t tesuto2[] = L"テスト2";
+ const wchar_t tesutoni[] = L"テスト二";
+ const wchar_t* result = ini.GetValue(kensa, tesuto2);
+ ASSERT_STREQ(result, tesutoni);
+}