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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/gtests/blenlib/BLI_ghash_performance_test.cc415
-rw-r--r--tests/gtests/blenlib/BLI_ghash_test.cc158
-rw-r--r--tests/gtests/blenlib/BLI_hash_mm2a_test.cc75
-rw-r--r--tests/gtests/blenlib/BLI_listbase_test.cc218
-rw-r--r--tests/gtests/blenlib/BLI_math_base_test.cc87
-rw-r--r--tests/gtests/blenlib/BLI_path_util_test.cc1
-rw-r--r--tests/gtests/blenlib/BLI_polyfill2d_test.cc518
-rw-r--r--tests/gtests/blenlib/BLI_ressource_strings.h602
-rw-r--r--tests/gtests/blenlib/BLI_stack_test.cc77
-rw-r--r--tests/gtests/blenlib/BLI_string_test.cc70
-rw-r--r--tests/gtests/blenlib/CMakeLists.txt6
-rw-r--r--tests/gtests/testing/testing_main.cc2
-rw-r--r--tests/python/CMakeLists.txt65
-rw-r--r--tests/python/batch_import.py4
-rw-r--r--tests/python/bl_load_addons.py61
-rw-r--r--tests/python/bl_load_py_modules.py42
-rw-r--r--tests/python/bl_mesh_modifiers.py3
-rw-r--r--tests/python/bl_pyapi_bpy_path.py41
-rw-r--r--tests/python/bl_pyapi_bpy_utils_units.py (renamed from tests/python/bl_pyapi_units.py)2
-rw-r--r--tests/python/bl_pyapi_mathutils.py31
-rw-r--r--tests/python/bl_rna_defaults.py117
-rw-r--r--tests/python/bl_rna_manual_reference.py (renamed from tests/python/bl_rna_wiki_reference.py)51
-rw-r--r--tests/python/bl_rst_completeness.py2
-rw-r--r--tests/python/bl_run_operators.py10
-rwxr-xr-xtests/python/cycles_render_tests.py166
-rw-r--r--tests/python/pep8.py25
-rw-r--r--tests/python/rst_to_doctree_mini.py21
27 files changed, 2805 insertions, 65 deletions
diff --git a/tests/gtests/blenlib/BLI_ghash_performance_test.cc b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
new file mode 100644
index 00000000000..fcee72466b7
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_ghash_performance_test.cc
@@ -0,0 +1,415 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+#include "BLI_ressource_strings.h"
+
+#define GHASH_INTERNAL_API
+
+extern "C" {
+#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_rand.h"
+#include "BLI_string.h"
+#include "PIL_time_utildefines.h"
+}
+
+/* Using http://corpora.uni-leipzig.de/downloads/eng_wikipedia_2010_1M-text.tar.gz
+ * (1 million of words, about 122MB of text) from http://corpora.informatik.uni-leipzig.de/download.html */
+//#define TEXT_CORPUS_PATH "/path/to/Téléchargements/eng_wikipedia_2010_1M-text/eng_wikipedia_2010_1M-sentences.txt"
+
+/* Resizing the hash has a huge cost over global filling operation! */
+//#define GHASH_RESERVE
+
+#define PRINTF_GHASH_STATS(_gh) \
+{ \
+ double q, lf, var, pempty, poverloaded; \
+ int bigb; \
+ q = BLI_ghash_calc_quality_ex((_gh), &lf, &var, &pempty, &poverloaded, &bigb); \
+ printf("GHash stats (%u entries):\n\t" \
+ "Quality (the lower the better): %f\n\tVariance (the lower the better): %f\n\tLoad: %f\n\t" \
+ "Empty buckets: %.2f%%\n\tOverloaded buckets: %.2f%% (biggest bucket: %d)\n", \
+ BLI_ghash_size(_gh), q, var, lf, pempty * 100.0, poverloaded * 100.0, bigb); \
+} void (0)
+
+
+/* Str: whole text, lines and words from a 'corpus' text. */
+
+static void str_ghash_tests(GHash *ghash, const char *id)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+#ifdef TEXT_CORPUS_PATH
+ size_t sz = 0;
+ char *data;
+ {
+ struct stat st;
+ if (stat(TEXT_CORPUS_PATH, &st) == 0)
+ sz = st.st_size;
+ }
+ if (sz != 0) {
+ FILE *f = fopen(TEXT_CORPUS_PATH, "r");
+
+ data = (char *)MEM_mallocN(sz + 1, __func__);
+ if (fread(data, sizeof(*data), sz, f) != sz) {
+ printf("ERROR in reading file %s!", TEXT_CORPUS_PATH);
+ MEM_freeN(data);
+ data = BLI_strdup(words10k);
+ }
+ data[sz] = '\0';
+ fclose(f);
+ }
+ else {
+ data = BLI_strdup(words10k);
+ }
+#else
+ char *data = BLI_strdup(words10k);
+#endif
+ char *data_p = BLI_strdup(data);
+ char *data_w = BLI_strdup(data);
+ char *data_bis = BLI_strdup(data);
+
+ {
+ char *p, *w, *c_p, *c_w;
+
+ TIMEIT_START(string_insert);
+
+#ifdef GHASH_RESERVE
+ BLI_ghash_reserve(ghash, strlen(data) / 32); /* rough estimation... */
+#endif
+
+ BLI_ghash_insert(ghash, data, SET_INT_IN_POINTER(data[0]));
+
+ for (p = c_p = data_p, w = c_w = data_w; *c_w; c_w++, c_p++) {
+ if (*c_p == '.') {
+ *c_p = *c_w = '\0';
+ if (!BLI_ghash_haskey(ghash, p)) {
+ BLI_ghash_insert(ghash, p, SET_INT_IN_POINTER(p[0]));
+ }
+ if (!BLI_ghash_haskey(ghash, w)) {
+ BLI_ghash_insert(ghash, w, SET_INT_IN_POINTER(w[0]));
+ }
+ p = c_p + 1;
+ w = c_w + 1;
+ }
+ else if (*c_w == ' ') {
+ *c_w = '\0';
+ if (!BLI_ghash_haskey(ghash, w)) {
+ BLI_ghash_insert(ghash, w, SET_INT_IN_POINTER(w[0]));
+ }
+ w = c_w + 1;
+ }
+ }
+
+ TIMEIT_END(string_insert);
+ }
+
+ PRINTF_GHASH_STATS(ghash);
+
+ {
+ char *p, *w, *c;
+ void *v;
+
+ TIMEIT_START(string_lookup);
+
+ v = BLI_ghash_lookup(ghash, data_bis);
+ EXPECT_EQ(data_bis[0], GET_INT_FROM_POINTER(v));
+
+ for (p = w = c = data_bis; *c; c++) {
+ if (*c == '.') {
+ *c = '\0';
+ v = BLI_ghash_lookup(ghash, w);
+ EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v));
+ v = BLI_ghash_lookup(ghash, p);
+ EXPECT_EQ(p[0], GET_INT_FROM_POINTER(v));
+ p = w = c + 1;
+ }
+ else if (*c == ' ') {
+ *c = '\0';
+ v = BLI_ghash_lookup(ghash, w);
+ EXPECT_EQ(w[0], GET_INT_FROM_POINTER(v));
+ w = c + 1;
+ }
+ }
+
+ TIMEIT_END(string_lookup);
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+ MEM_freeN(data);
+ MEM_freeN(data_p);
+ MEM_freeN(data_w);
+ MEM_freeN(data_bis);
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(ghash, TextGHash)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
+
+ str_ghash_tests(ghash, "StrGHash - GHash");
+}
+
+TEST(ghash, TextMurmur2a)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_strhash_p_murmur, BLI_ghashutil_strcmp, __func__);
+
+ str_ghash_tests(ghash, "StrGHash - Murmur");
+}
+
+
+/* Int: uniform 100M first integers. */
+
+static void int_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+ {
+ unsigned int i = nbr;
+
+ TIMEIT_START(int_insert);
+
+#ifdef GHASH_RESERVE
+ BLI_ghash_reserve(ghash, nbr);
+#endif
+
+ while (i--) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(i), SET_UINT_IN_POINTER(i));
+ }
+
+ TIMEIT_END(int_insert);
+ }
+
+ PRINTF_GHASH_STATS(ghash);
+
+ {
+ unsigned int i = nbr;
+
+ TIMEIT_START(int_lookup);
+
+ while (i--) {
+ void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(i));
+ EXPECT_EQ(i, GET_UINT_FROM_POINTER(v));
+ }
+
+ TIMEIT_END(int_lookup);
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(ghash, IntGHash12000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ int_ghash_tests(ghash, "IntGHash - GHash - 12000", 12000);
+}
+
+TEST(ghash, IntGHash100000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ int_ghash_tests(ghash, "IntGHash - GHash - 100000000", 100000000);
+}
+
+TEST(ghash, IntMurmur2a12000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ int_ghash_tests(ghash, "IntGHash - Murmur - 12000", 12000);
+}
+
+TEST(ghash, IntMurmur2a100000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ int_ghash_tests(ghash, "IntGHash - Murmur - 100000000", 100000000);
+}
+
+
+/* Int: random 50M integers. */
+
+static void randint_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+ unsigned int *data = (unsigned int *)MEM_mallocN(sizeof(*data) * (size_t)nbr, __func__);
+ unsigned int *dt;
+ unsigned int i;
+
+ {
+ RNG *rng = BLI_rng_new(0);
+ for (i = nbr, dt = data; i--; dt++) {
+ *dt = BLI_rng_get_uint(rng);
+ }
+ BLI_rng_free(rng);
+ }
+
+ {
+ TIMEIT_START(int_insert);
+
+#ifdef GHASH_RESERVE
+ BLI_ghash_reserve(ghash, nbr);
+#endif
+
+ for (i = nbr, dt = data; i--; dt++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*dt), SET_UINT_IN_POINTER(*dt));
+ }
+
+ TIMEIT_END(int_insert);
+ }
+
+ PRINTF_GHASH_STATS(ghash);
+
+ {
+ TIMEIT_START(int_lookup);
+
+ for (i = nbr, dt = data; i--; dt++) {
+ void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*dt));
+ EXPECT_EQ(*dt, GET_UINT_FROM_POINTER(v));
+ }
+
+ TIMEIT_END(int_lookup);
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(ghash, IntRandGHash12000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - GHash - 12000", 12000);
+}
+
+TEST(ghash, IntRandGHash50000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - GHash - 50000000", 50000000);
+}
+
+TEST(ghash, IntRandMurmur2a12000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - Murmur - 12000", 12000);
+}
+
+TEST(ghash, IntRandMurmur2a50000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p_murmur, BLI_ghashutil_intcmp, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - Murmur - 50000000", 50000000);
+}
+
+static unsigned int ghashutil_tests_nohash_p(const void *p)
+{
+ return GET_UINT_FROM_POINTER(p);
+}
+
+static bool ghashutil_tests_cmp_p(const void *a, const void *b)
+{
+ return a != b;
+}
+
+TEST(ghash, Int4NoHash12000)
+{
+ GHash *ghash = BLI_ghash_new(ghashutil_tests_nohash_p, ghashutil_tests_cmp_p, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - No Hash - 12000", 12000);
+}
+
+TEST(ghash, Int4NoHash50000000)
+{
+ GHash *ghash = BLI_ghash_new(ghashutil_tests_nohash_p, ghashutil_tests_cmp_p, __func__);
+
+ randint_ghash_tests(ghash, "RandIntGHash - No Hash - 50000000", 50000000);
+}
+
+
+/* Int_v4: 20M of randomly-generated integer vectors. */
+
+static void int4_ghash_tests(GHash *ghash, const char *id, const unsigned int nbr)
+{
+ printf("\n========== STARTING %s ==========\n", id);
+
+ unsigned int (*data)[4] = (unsigned int (*)[4])MEM_mallocN(sizeof(*data) * (size_t)nbr, __func__);
+ unsigned int (*dt)[4];
+ unsigned int i, j;
+
+ {
+ RNG *rng = BLI_rng_new(0);
+ for (i = nbr, dt = data; i--; dt++) {
+ for (j = 4; j--; ) {
+ (*dt)[j] = BLI_rng_get_uint(rng);
+ }
+ }
+ BLI_rng_free(rng);
+ }
+
+ {
+ TIMEIT_START(int_v4_insert);
+
+#ifdef GHASH_RESERVE
+ BLI_ghash_reserve(ghash, nbr);
+#endif
+
+ for (i = nbr, dt = data; i--; dt++) {
+ BLI_ghash_insert(ghash, *dt, SET_UINT_IN_POINTER(i));
+ }
+
+ TIMEIT_END(int_v4_insert);
+ }
+
+ PRINTF_GHASH_STATS(ghash);
+
+ {
+ TIMEIT_START(int_v4_lookup);
+
+ for (i = nbr, dt = data; i--; dt++) {
+ void *v = BLI_ghash_lookup(ghash, (void *)(*dt));
+ EXPECT_EQ(i, GET_UINT_FROM_POINTER(v));
+ }
+
+ TIMEIT_END(int_v4_lookup);
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+ MEM_freeN(data);
+
+ printf("========== ENDED %s ==========\n\n", id);
+}
+
+TEST(ghash, Int4GHash2000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
+ int4_ghash_tests(ghash, "Int4GHash - GHash - 2000", 2000);
+}
+
+TEST(ghash, Int4GHash20000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
+ int4_ghash_tests(ghash, "Int4GHash - GHash - 20000000", 20000000);
+}
+
+TEST(ghash, Int4Murmur2a2000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p_murmur, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
+ int4_ghash_tests(ghash, "Int4GHash - Murmur - 2000", 2000);
+}
+
+TEST(ghash, Int4Murmur2a20000000)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_uinthash_v4_p_murmur, BLI_ghashutil_uinthash_v4_cmp, __func__);
+
+ int4_ghash_tests(ghash, "Int4GHash - Murmur - 20000000", 20000000);
+}
diff --git a/tests/gtests/blenlib/BLI_ghash_test.cc b/tests/gtests/blenlib/BLI_ghash_test.cc
new file mode 100644
index 00000000000..5fe43d14cbe
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_ghash_test.cc
@@ -0,0 +1,158 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+#define GHASH_INTERNAL_API
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_ghash.h"
+#include "BLI_rand.h"
+}
+
+#define TESTCASE_SIZE 10000
+
+/* Only keeping this in case here, for now. */
+#define PRINTF_GHASH_STATS(_gh) \
+{ \
+ double q, lf, var, pempty, poverloaded; \
+ int bigb; \
+ q = BLI_ghash_calc_quality_ex((_gh), &lf, &var, &pempty, &poverloaded, &bigb); \
+ printf("GHash stats (%d entries):\n\t" \
+ "Quality (the lower the better): %f\n\tVariance (the lower the better): %f\n\tLoad: %f\n\t" \
+ "Empty buckets: %.2f%%\n\tOverloaded buckets: %.2f%% (biggest bucket: %d)\n", \
+ BLI_ghash_size(_gh), q, var, lf, pempty * 100.0, poverloaded * 100.0, bigb); \
+} void (0)
+
+/* Note: for pure-ghash testing, nature of the keys and data have absolutely no importance! So here we just use mere
+ * random integers stored in pointers. */
+
+static void init_keys(unsigned int keys[TESTCASE_SIZE], const int seed)
+{
+ RNG *rng = BLI_rng_new(seed);
+ unsigned int *k;
+ int i;
+
+ for (i = 0, k = keys; i < TESTCASE_SIZE; ) {
+ /* Risks of collision are low, but they do exist.
+ * And we cannot use a GSet, since we test that here! */
+ int j, t = BLI_rng_get_uint(rng);
+ for (j = i; j--; ) {
+ if (keys[j] == t) {
+ continue;
+ }
+ }
+ *k = t;
+ i++;
+ k++;
+ }
+ BLI_rng_free(rng);
+}
+
+/* Here we simply insert and then lookup all keys, ensuring we do get back the expected stored 'data'. */
+TEST(ghash, InsertLookup)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ unsigned int keys[TESTCASE_SIZE], *k;
+ int i;
+
+ init_keys(keys, 0);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
+ }
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ void *v = BLI_ghash_lookup(ghash, SET_UINT_IN_POINTER(*k));
+ EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+}
+
+/* Here we simply insert and then remove all keys, ensuring we do get an empty, unshrinked ghash. */
+TEST(ghash, InsertRemove)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ unsigned int keys[TESTCASE_SIZE], *k;
+ int i, bkt_size;
+
+ init_keys(keys, 10);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
+ }
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ bkt_size = BLI_ghash_buckets_size(ghash);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL);
+ EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ }
+
+ EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_EQ(bkt_size, BLI_ghash_buckets_size(ghash));
+
+ BLI_ghash_free(ghash, NULL, NULL);
+}
+
+/* Same as above, but this time we allow ghash to shrink. */
+TEST(ghash, InsertRemoveShrink)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ unsigned int keys[TESTCASE_SIZE], *k;
+ int i, bkt_size;
+
+ BLI_ghash_flag_set(ghash, GHASH_FLAG_ALLOW_SHRINK);
+ init_keys(keys, 20);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
+ }
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+ bkt_size = BLI_ghash_buckets_size(ghash);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ void *v = BLI_ghash_popkey(ghash, SET_UINT_IN_POINTER(*k), NULL);
+ EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ }
+
+ EXPECT_EQ(0, BLI_ghash_size(ghash));
+ EXPECT_LT(BLI_ghash_buckets_size(ghash), bkt_size);
+
+ BLI_ghash_free(ghash, NULL, NULL);
+}
+
+/* Check copy. */
+TEST(ghash, Copy)
+{
+ GHash *ghash = BLI_ghash_new(BLI_ghashutil_inthash_p, BLI_ghashutil_intcmp, __func__);
+ GHash *ghash_copy;
+ unsigned int keys[TESTCASE_SIZE], *k;
+ int i;
+
+ init_keys(keys, 30);
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ BLI_ghash_insert(ghash, SET_UINT_IN_POINTER(*k), SET_UINT_IN_POINTER(*k));
+ }
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash));
+
+ ghash_copy = BLI_ghash_copy(ghash, NULL, NULL);
+
+ EXPECT_EQ(TESTCASE_SIZE, BLI_ghash_size(ghash_copy));
+ EXPECT_EQ(BLI_ghash_buckets_size(ghash), BLI_ghash_buckets_size(ghash_copy));
+
+ for (i = TESTCASE_SIZE, k = keys; i--; k++) {
+ void *v = BLI_ghash_lookup(ghash_copy, SET_UINT_IN_POINTER(*k));
+ EXPECT_EQ(*k, GET_UINT_FROM_POINTER(v));
+ }
+
+ BLI_ghash_free(ghash, NULL, NULL);
+ BLI_ghash_free(ghash_copy, NULL, NULL);
+}
diff --git a/tests/gtests/blenlib/BLI_hash_mm2a_test.cc b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
new file mode 100644
index 00000000000..b35a1a809d6
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_hash_mm2a_test.cc
@@ -0,0 +1,75 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+extern "C" {
+#include "BLI_hash_mm2a.h"
+}
+
+/* Note: Reference results are taken from reference implementation (cpp code, CMurmurHash2A variant):
+ * https://smhasher.googlecode.com/svn-history/r130/trunk/MurmurHash2.cpp
+ */
+
+TEST(hash_mm2a, MM2ABasic)
+{
+ BLI_HashMurmur2A mm2;
+
+ const char *data = "Blender";
+
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data, strlen(data));
+#ifdef __LITTLE_ENDIAN__
+ EXPECT_EQ(1633988145, BLI_hash_mm2a_end(&mm2));
+#else
+ EXPECT_EQ(959283772, BLI_hash_mm2a_end(&mm2));
+#endif
+}
+
+TEST(hash_mm2a, MM2AConcatenateStrings)
+{
+ BLI_HashMurmur2A mm2;
+ uint32_t hash;
+
+ const char *data1 = "Blender";
+ const char *data2 = " is ";
+ const char *data3 = "FaNtAsTiC";
+ const char *data123 = "Blender is FaNtAsTiC";
+
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data1, strlen(data1));
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data2, strlen(data2));
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data3, strlen(data3));
+ hash = BLI_hash_mm2a_end(&mm2);
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)data123, strlen(data123));
+#ifdef __LITTLE_ENDIAN__
+ EXPECT_EQ(1545105348, hash);
+#else
+ EXPECT_EQ(2604964730, hash);
+#endif
+ EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2));
+}
+
+TEST(hash_mm2a, MM2AIntegers)
+{
+ BLI_HashMurmur2A mm2;
+ uint32_t hash;
+
+ const int ints[4] = {1, 2, 3, 4};
+
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add_int(&mm2, ints[0]);
+ BLI_hash_mm2a_add_int(&mm2, ints[1]);
+ BLI_hash_mm2a_add_int(&mm2, ints[2]);
+ BLI_hash_mm2a_add_int(&mm2, ints[3]);
+ hash = BLI_hash_mm2a_end(&mm2);
+ BLI_hash_mm2a_init(&mm2, 0);
+ BLI_hash_mm2a_add(&mm2, (const unsigned char *)ints, sizeof(ints));
+ /* Yes, same hash here on little and big endian. */
+#ifdef __LITTLE_ENDIAN__
+ EXPECT_EQ(405493096, hash);
+#else
+ EXPECT_EQ(405493096, hash);
+#endif
+ EXPECT_EQ(hash, BLI_hash_mm2a_end(&mm2));
+}
diff --git a/tests/gtests/blenlib/BLI_listbase_test.cc b/tests/gtests/blenlib/BLI_listbase_test.cc
index 4b4d5d80a43..994b8f74541 100644
--- a/tests/gtests/blenlib/BLI_listbase_test.cc
+++ b/tests/gtests/blenlib/BLI_listbase_test.cc
@@ -3,10 +3,69 @@
#include "testing/testing.h"
extern "C" {
+#include "BLI_array_utils.h"
#include "BLI_listbase.h"
#include "MEM_guardedalloc.h"
+
+#include "BLI_string.h"
+#include "BLI_path_util.h"
+#include "BLI_ressource_strings.h"
+}
+
+
+/* local validation function */
+static bool listbase_is_valid(const ListBase *listbase)
+{
+#define TESTFAIL(test) \
+ if (!(test)) goto fail;
+
+ if (listbase->first) {
+ const Link *prev, *link;
+ link = (Link *)listbase->first;
+ TESTFAIL(link->prev == NULL);
+
+ link = (Link *)listbase->last;
+ TESTFAIL(link->next == NULL);
+
+ prev = NULL;
+ link = (Link *)listbase->first;
+ do {
+ TESTFAIL(link->prev == prev);
+ } while ((prev = link), (link = link->next));
+ TESTFAIL(prev == listbase->last);
+
+ prev = NULL;
+ link = (Link *)listbase->last;
+ do {
+ TESTFAIL(link->next == prev);
+ } while ((prev = link), (link = link->prev));
+ TESTFAIL(prev == listbase->first);
+ }
+ else {
+ TESTFAIL(listbase->last == NULL);
+ }
+#undef TESTFAIL
+
+ return true;
+
+fail:
+ return false;
+}
+
+static int char_switch(char *string, char ch_src, char ch_dst)
+{
+ int tot = 0;
+ while (*string != 0) {
+ if (*string == ch_src) {
+ *string = ch_dst;
+ tot++;
+ }
+ string++;
+ }
+ return tot;
}
+
TEST(listbase, FindLinkOrIndex)
{
ListBase lb;
@@ -37,3 +96,162 @@ TEST(listbase, FindLinkOrIndex)
BLI_freelistN(&lb);
}
+
+
+/* -------------------------------------------------------------------- */
+/* Sort utilities & test */
+
+static int testsort_array_str_cmp(const void *a, const void *b)
+{
+ int i = strcmp(*(const char **)a, *(const char **)b);
+ return (i > 0) ? 1 : (i < 0) ? -1 : 0;
+}
+
+static int testsort_listbase_str_cmp(const void *a, const void *b)
+{
+ const LinkData *link_a = (LinkData *)a;
+ const LinkData *link_b = (LinkData *)b;
+ int i = strcmp((const char *)link_a->data, (const char *)link_b->data);
+ return (i > 0) ? 1 : (i < 0) ? -1 : 0;
+}
+
+static int testsort_array_str_cmp_reverse(const void *a, const void *b)
+{
+ return -testsort_array_str_cmp(a, b);
+}
+
+static int testsort_listbase_str_cmp_reverse(const void *a, const void *b)
+{
+ return -testsort_listbase_str_cmp(a, b);
+}
+
+/* check array and listbase compare */
+static bool testsort_listbase_array_str_cmp(ListBase *lb, char **arr, int arr_tot)
+{
+ LinkData *link_step;
+ int i;
+
+ link_step = (LinkData *)lb->first;
+ for (i = 0; i < arr_tot; i++) {
+ if (strcmp(arr[i], (char *)link_step->data) != 0) {
+ return false;
+ }
+ link_step = link_step->next;
+ }
+ if (link_step) {
+ return false;
+ }
+
+ return true;
+}
+
+/* assumes nodes are allocated in-order */
+static bool testsort_listbase_sort_is_stable(ListBase *lb, bool forward)
+{
+ LinkData *link_step;
+
+ link_step = (LinkData *)lb->first;
+ while (link_step && link_step->next) {
+ if (strcmp((const char *)link_step->data, (const char *)link_step->next->data) == 0) {
+ if ((link_step < link_step->next) != forward) {
+ return false;
+ }
+ }
+ link_step = link_step->next;
+ }
+ return true;
+}
+
+TEST(listbase, Sort)
+{
+ const int words_len = sizeof(words10k) - 1;
+ char *words = BLI_strdupn(words10k, words_len);
+ int words_tot;
+ char **words_arr; /* qsort for comparison */
+ int i;
+ char *w_step;
+ ListBase words_lb;
+ LinkData *words_linkdata_arr;
+
+ /* delimit words */
+ words_tot = 1 + char_switch(words, ' ', '\0');
+
+ words_arr = (char **)MEM_mallocN(sizeof(*words_arr) * words_tot, __func__);
+
+ words_linkdata_arr = (LinkData *)MEM_mallocN(sizeof(*words_linkdata_arr) * words_tot, __func__);
+
+ /* create array */
+ w_step = words;
+ for (i = 0; i < words_tot; i++) {
+ words_arr[i] = w_step;
+ w_step += strlen(w_step) + 1;
+ }
+
+ /* sort empty list */
+ {
+ BLI_listbase_clear(&words_lb);
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp);
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ }
+
+ /* sort single single */
+ {
+ LinkData link;
+ link.data = words;
+ BLI_addtail(&words_lb, &link);
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp);
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ BLI_listbase_clear(&words_lb);
+ }
+
+ /* create listbase */
+ BLI_listbase_clear(&words_lb);
+ w_step = words;
+ for (i = 0; i < words_tot; i++) {
+ LinkData *link = &words_linkdata_arr[i];
+ link->data = w_step;
+ BLI_addtail(&words_lb, link);
+ w_step += strlen(w_step) + 1;
+ }
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+
+ /* sort (forward) */
+ {
+ qsort(words_arr, words_tot, sizeof(*words_arr), testsort_array_str_cmp);
+
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp);
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, true));
+ }
+
+ /* sort (reverse) */
+ {
+ qsort(words_arr, words_tot, sizeof(*words_arr), testsort_array_str_cmp_reverse);
+
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp_reverse);
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, true));
+ }
+
+ /* sort (forward but after reversing, test stability in alternate direction) */
+ {
+ BLI_array_reverse(words_arr, words_tot);
+ BLI_listbase_reverse(&words_lb);
+
+ EXPECT_TRUE(listbase_is_valid(&words_lb));
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, false));
+
+ /* and again */
+ BLI_array_reverse(words_arr, words_tot);
+ BLI_listbase_sort(&words_lb, testsort_listbase_str_cmp_reverse);
+ EXPECT_TRUE(testsort_listbase_array_str_cmp(&words_lb, words_arr, words_tot));
+ EXPECT_TRUE(testsort_listbase_sort_is_stable(&words_lb, false));
+ }
+
+ MEM_freeN(words);
+ MEM_freeN(words_arr);
+ MEM_freeN(words_linkdata_arr);
+}
diff --git a/tests/gtests/blenlib/BLI_math_base_test.cc b/tests/gtests/blenlib/BLI_math_base_test.cc
new file mode 100644
index 00000000000..0059eb54482
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_math_base_test.cc
@@ -0,0 +1,87 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+#include "BLI_math.h"
+
+/* In tests below, when we are using -1.0f as max_diff value, we actually turn the function into a pure-ULP one. */
+
+/* Put this here, since we cannot use BLI_assert() in inline math files it seems... */
+TEST(math_base, CompareFFRelativeValid)
+{
+ EXPECT_TRUE(sizeof(float) == sizeof(int));
+}
+
+TEST(math_base, CompareFFRelativeNormal)
+{
+ float f1 = 1.99999988f; /* *(float *)&(*(int *)&f2 - 1) */
+ float f2 = 2.00000000f;
+ float f3 = 2.00000048f; /* *(float *)&(*(int *)&f2 + 2) */
+ float f4 = 2.10000000f; /* *(float *)&(*(int *)&f2 + 419430) */
+
+ const float max_diff = FLT_EPSILON * 0.1f;
+
+ EXPECT_TRUE(compare_ff_relative(f1, f2, max_diff, 1));
+ EXPECT_TRUE(compare_ff_relative(f2, f1, max_diff, 1));
+
+ EXPECT_TRUE(compare_ff_relative(f3, f2, max_diff, 2));
+ EXPECT_TRUE(compare_ff_relative(f2, f3, max_diff, 2));
+
+ EXPECT_FALSE(compare_ff_relative(f3, f2, max_diff, 1));
+ EXPECT_FALSE(compare_ff_relative(f2, f3, max_diff, 1));
+
+
+ EXPECT_FALSE(compare_ff_relative(f3, f2, -1.0f, 1));
+ EXPECT_FALSE(compare_ff_relative(f2, f3, -1.0f, 1));
+
+ EXPECT_TRUE(compare_ff_relative(f3, f2, -1.0f, 2));
+ EXPECT_TRUE(compare_ff_relative(f2, f3, -1.0f, 2));
+
+
+ EXPECT_FALSE(compare_ff_relative(f4, f2, max_diff, 64));
+ EXPECT_FALSE(compare_ff_relative(f2, f4, max_diff, 64));
+
+ EXPECT_TRUE(compare_ff_relative(f1, f3, max_diff, 64));
+ EXPECT_TRUE(compare_ff_relative(f3, f1, max_diff, 64));
+}
+
+TEST(math_base, CompareFFRelativeZero)
+{
+ float f0 = 0.0f;
+ float f1 = 4.2038954e-045f; /* *(float *)&(*(int *)&f0 + 3) */
+
+ float fn0 = -0.0f;
+ float fn1 = -2.8025969e-045f; /* *(float *)&(*(int *)&fn0 - 2) */
+
+ const float max_diff = FLT_EPSILON * 0.1f;
+
+ EXPECT_TRUE(compare_ff_relative(f0, f1, -1.0f, 3));
+ EXPECT_TRUE(compare_ff_relative(f1, f0, -1.0f, 3));
+
+ EXPECT_FALSE(compare_ff_relative(f0, f1, -1.0f, 1));
+ EXPECT_FALSE(compare_ff_relative(f1, f0, -1.0f, 1));
+
+ EXPECT_TRUE(compare_ff_relative(fn0, fn1, -1.0f, 8));
+ EXPECT_TRUE(compare_ff_relative(fn1, fn0, -1.0f, 8));
+
+
+ EXPECT_TRUE(compare_ff_relative(f0, f1, max_diff, 1));
+ EXPECT_TRUE(compare_ff_relative(f1, f0, max_diff, 1));
+
+ EXPECT_TRUE(compare_ff_relative(fn0, f0, max_diff, 1));
+ EXPECT_TRUE(compare_ff_relative(f0, fn0, max_diff, 1));
+
+ EXPECT_TRUE(compare_ff_relative(f0, fn1, max_diff, 1));
+ EXPECT_TRUE(compare_ff_relative(fn1, f0, max_diff, 1));
+
+
+ /* Note: in theory, this should return false, since 0.0f and -0.0f have 0x80000000 diff,
+ * but overflow in substraction seems to break something here
+ * (abs(*(int *)&fn0 - *(int *)&f0) == 0x80000000 == fn0), probably because int32 cannot hold this abs value.
+ * this is yet another illustration of why one shall never use (near-)zero floats in pure-ULP comparison. */
+// EXPECT_FALSE(compare_ff_relative(fn0, f0, -1.0f, 1024));
+// EXPECT_FALSE(compare_ff_relative(f0, fn0, -1.0f, 1024));
+
+ EXPECT_FALSE(compare_ff_relative(fn0, f1, -1.0f, 1024));
+ EXPECT_FALSE(compare_ff_relative(f1, fn0, -1.0f, 1024));
+}
diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc
index ea761bcf32e..c4ef7c2c970 100644
--- a/tests/gtests/blenlib/BLI_path_util_test.cc
+++ b/tests/gtests/blenlib/BLI_path_util_test.cc
@@ -31,6 +31,7 @@ const char *GHOST_getSystemDir(int version, const char *versionstr)
struct ImBuf;
void IMB_freeImBuf(struct ImBuf *ibuf) {}
+struct ImBuf *IMB_dupImBuf(struct ImBuf *ibuf) {return NULL;}
#ifdef __linux__
char *zLhm65070058860608_br_find_exe(const char *default_exe)
diff --git a/tests/gtests/blenlib/BLI_polyfill2d_test.cc b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
new file mode 100644
index 00000000000..8ca19b11632
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_polyfill2d_test.cc
@@ -0,0 +1,518 @@
+/* Apache License, Version 2.0 */
+
+#include "testing/testing.h"
+
+/* Use to write out OBJ files, handy for checking output */
+// #define USE_OBJ_PREVIEW
+
+/* test every possible offset and reverse */
+#define USE_COMBINATIONS_ALL
+#define USE_BEAUTIFY
+
+extern "C" {
+#include "BLI_array_utils.h"
+#include "BLI_polyfill2d.h"
+#include "BLI_math.h"
+#include "BLI_edgehash.h"
+#include "MEM_guardedalloc.h"
+
+#ifdef USE_OBJ_PREVIEW
+# include "BLI_string.h"
+#endif
+
+#ifdef USE_BEAUTIFY
+#include "BLI_polyfill2d_beautify.h"
+#include "BLI_memarena.h"
+#include "BLI_heap.h"
+#endif
+}
+
+static void polyfill_to_obj(
+ const char *id,
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot);
+
+/* -------------------------------------------------------------------- */
+/* test utility functions */
+
+#define TRI_ERROR_VALUE (unsigned int)-1
+
+static void test_valid_polyfill_prepare(unsigned int tris[][3], unsigned int tris_tot)
+{
+ unsigned int i;
+ for (i = 0; i < tris_tot; i++) {
+ unsigned int j;
+ for (j = 0; j < 3; j++) {
+ tris[i][j] = TRI_ERROR_VALUE;
+ }
+ }
+}
+
+/**
+ * Basic check for face index values:
+ *
+ * - no duplicates.
+ * - all tris set.
+ * - all verts used at least once.
+ */
+static void test_polyfill_simple(
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ unsigned int i;
+ int *tot_used = (int *)MEM_callocN(poly_tot * sizeof(int), __func__);
+ for (i = 0; i < tris_tot; i++) {
+ unsigned int j;
+ for (j = 0; j < 3; j++) {
+ EXPECT_NE(TRI_ERROR_VALUE, tris[i][j]);
+ tot_used[tris[i][j]] += 1;
+ }
+ EXPECT_NE(tris[i][0], tris[i][1]);
+ EXPECT_NE(tris[i][1], tris[i][2]);
+ EXPECT_NE(tris[i][2], tris[i][0]);
+ }
+ for (i = 0; i < poly_tot; i++) {
+ EXPECT_NE(0, tot_used[i]);
+ }
+ MEM_freeN(tot_used);
+}
+
+static void test_polyfill_topology(
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ EdgeHash *edgehash = BLI_edgehash_new(__func__);
+ EdgeHashIterator *ehi;
+ unsigned int i;
+ for (i = 0; i < tris_tot; i++) {
+ unsigned int j;
+ for (j = 0; j < 3; j++) {
+ const unsigned int v1 = tris[i][j];
+ const unsigned int v2 = tris[i][(j + 1) % 3];
+ void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
+ if (p) {
+ *p = (void *)((intptr_t)*p + (intptr_t)1);
+ }
+ else {
+ BLI_edgehash_insert(edgehash, v1, v2, (void *)(intptr_t)1);
+ }
+ }
+ }
+ EXPECT_EQ(poly_tot + (poly_tot - 3), BLI_edgehash_size(edgehash));
+
+ for (i = 0; i < poly_tot; i++) {
+ const unsigned int v1 = i;
+ const unsigned int v2 = (i + 1) % poly_tot;
+ void **p = BLI_edgehash_lookup_p(edgehash, v1, v2);
+ EXPECT_EQ(1, (void *)p != NULL);
+ EXPECT_EQ(1, (intptr_t)*p);
+ }
+
+ for (ehi = BLI_edgehashIterator_new(edgehash), i = 0;
+ BLI_edgehashIterator_isDone(ehi) == false;
+ BLI_edgehashIterator_step(ehi), i++)
+ {
+ void **p = BLI_edgehashIterator_getValue_p(ehi);
+ EXPECT_EQ(true, ELEM((intptr_t)*p, 1, 2));
+ }
+
+ BLI_edgehash_free(edgehash, NULL);
+}
+
+/**
+ * Check all faces are flipped the same way
+ */
+static void test_polyfill_winding(
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ unsigned int i;
+ unsigned int count[2] = {0, 0};
+ for (i = 0; i < tris_tot; i++) {
+ float winding_test = cross_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]);
+ if (fabsf(winding_test) > FLT_EPSILON) {
+ count[winding_test < 0.0f] += 1;
+ }
+ }
+ EXPECT_EQ(true, ELEM(0, count[0], count[1]));
+}
+
+/**
+ * Check the accumulated triangle area is close to the original area.
+ */
+static void test_polyfill_area(
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ unsigned int i;
+ const float area_tot = area_poly_v2(poly, poly_tot);
+ float area_tot_tris = 0.0f;
+ const float eps_abs = 0.00001f;
+ const float eps = area_tot > 1.0f ? (area_tot * eps_abs) : eps_abs;
+ for (i = 0; i < tris_tot; i++) {
+ area_tot_tris += area_tri_v2(poly[tris[i][0]], poly[tris[i][1]], poly[tris[i][2]]);
+ }
+ EXPECT_NEAR(area_tot, area_tot_tris, eps);
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Macro and helpers to manage checking */
+/**
+ * Main template for polyfill testing.
+ */
+static void test_polyfill_template_check(
+ const char *id, bool is_degenerate,
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ test_polyfill_simple(poly, poly_tot, tris, tris_tot);
+ test_polyfill_topology(poly, poly_tot, tris, tris_tot);
+ if (!is_degenerate) {
+ test_polyfill_winding(poly, poly_tot, tris, tris_tot);
+
+ test_polyfill_area(poly, poly_tot, tris, tris_tot);
+ }
+ polyfill_to_obj(id, poly, poly_tot, tris, tris_tot);
+}
+
+static void test_polyfill_template(
+ const char *id, bool is_degenerate,
+ const float poly[][2], const unsigned int poly_tot,
+ unsigned int tris[][3], const unsigned int tris_tot)
+{
+ test_valid_polyfill_prepare(tris, tris_tot);
+ BLI_polyfill_calc(poly, poly_tot, 0, tris);
+
+ /* check all went well */
+ test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+
+#ifdef USE_BEAUTIFY
+ /* check beautify gives good results too */
+ {
+ MemArena *pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
+ Heap *pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE);
+ EdgeHash *pf_ehash = BLI_edgehash_new_ex(__func__, BLI_POLYFILL_ALLOC_NGON_RESERVE);
+
+ BLI_polyfill_beautify(
+ poly, poly_tot, tris,
+ pf_arena, pf_heap, pf_ehash);
+
+ test_polyfill_template_check(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+
+ BLI_memarena_free(pf_arena);
+ BLI_heap_free(pf_heap, NULL);
+ BLI_edgehash_free(pf_ehash, NULL);
+ }
+#endif
+}
+
+#ifdef USE_COMBINATIONS_ALL
+static void test_polyfill_template_main(
+ const char *id, bool is_degenerate,
+ const float poly[][2], const unsigned int poly_tot,
+ unsigned int tris[][3], const unsigned int tris_tot)
+{
+ /* overkill? - try at _every_ offset & reverse */
+ unsigned int poly_reverse;
+ float (*poly_copy)[2] = (float (*)[2])MEM_mallocN(sizeof(float[2]) * poly_tot, id);
+ float tmp[2];
+
+ memcpy(poly_copy, poly, sizeof(float[2]) * poly_tot);
+
+ for (poly_reverse = 0; poly_reverse < 2; poly_reverse++) {
+ unsigned int poly_cycle;
+
+ if (poly_reverse) {
+ BLI_array_reverse(poly_copy, poly_tot);
+ }
+
+ for (poly_cycle = 0; poly_cycle < poly_tot; poly_cycle++) {
+ // printf("polytest %s ofs=%d, reverse=%d\n", id, poly_cycle, poly_reverse);
+ test_polyfill_template(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+
+ /* cycle */
+ copy_v2_v2(tmp, poly_copy[0]);
+ memmove(&poly_copy[0], &poly_copy[1], (poly_tot - 1) * sizeof(float[2]));
+ copy_v2_v2(poly_copy[poly_tot - 1], tmp);
+ }
+ }
+
+ MEM_freeN(poly_copy);
+}
+#else /* USE_COMBINATIONS_ALL */
+static void test_polyfill_template_main(
+ const char *id, bool is_degenerate,
+ const float poly[][2], const unsigned int poly_tot,
+ unsigned int tris[][3], const unsigned int tris_tot)
+{
+ test_polyfill_template(id, is_degenerate, poly, poly_tot, tris, tris_tot);
+}
+#endif /* USE_COMBINATIONS_ALL */
+
+#define TEST_POLYFILL_TEMPLATE_STATIC(poly, is_degenerate) \
+{ \
+ unsigned int tris[POLY_TRI_COUNT(ARRAY_SIZE(poly))][3]; \
+ const unsigned int poly_tot = ARRAY_SIZE(poly); \
+ const unsigned int tris_tot = ARRAY_SIZE(tris); \
+ const char *id = typeid(*this).name(); \
+ \
+ test_polyfill_template_main(id, is_degenerate, poly, poly_tot, tris, tris_tot); \
+} (void)0
+
+/* -------------------------------------------------------------------- */
+/* visualisation functions (not needed for testing) */
+
+#ifdef USE_OBJ_PREVIEW
+static void polyfill_to_obj(
+ const char *id,
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ char path[1024];
+ FILE *f;
+ unsigned int i;
+
+ BLI_snprintf(path, sizeof(path), "%s.obj", id);
+
+ f = fopen(path, "w");
+ if (!f) {
+ return;
+ }
+
+ for (i = 0; i < poly_tot; i++) {
+ fprintf(f, "v %f %f 0.0\n", UNPACK2(poly[i]));
+ }
+
+ for (i = 0; i < tris_tot; i++) {
+ fprintf(f, "f %u %u %u\n", UNPACK3_EX(1 +, tris[i], ));
+ }
+
+ fclose(f);
+}
+#else
+static void polyfill_to_obj(
+ const char *id,
+ const float poly[][2], const unsigned int poly_tot,
+ const unsigned int tris[][3], const unsigned int tris_tot)
+{
+ (void)id;
+ (void)poly, (void)poly_tot;
+ (void)tris, (void)tris_tot;
+}
+#endif /* USE_OBJ_PREVIEW */
+
+
+/* -------------------------------------------------------------------- */
+/* tests */
+
+#define POLY_TRI_COUNT(len) ((len) - 2)
+
+
+/* A counterclockwise triangle */
+TEST(polyfill2d, TriangleCCW)
+{
+ const float poly[][2] = {{0, 0}, {0, 1}, {1, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* A counterclockwise square */
+TEST(polyfill2d, SquareCCW)
+{
+ const float poly[][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* A clockwise square */
+TEST(polyfill2d, SquareCW)
+{
+ const float poly[][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Starfleet insigna */
+TEST(polyfill2d, Starfleet)
+{
+ const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Starfleet insigna with repeated point */
+TEST(polyfill2d, StarfleetDegenerate)
+{
+ const float poly[][2] = {{0, 0}, {0.6f, 0.4f}, {0.6f, 0.4f}, {1, 0}, {0.5f, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Three collinear points */
+TEST(polyfill2d, 3Colinear)
+{
+ const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Four collinear points */
+TEST(polyfill2d, 4Colinear)
+{
+ const float poly[][2] = {{0, 0}, {1, 0}, {2, 0}, {3, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Non-consecutive collinear points */
+TEST(polyfill2d, UnorderedColinear)
+{
+ const float poly[][2] = {{0, 0}, {1, 1}, {2, 0}, {3, 1}, {4, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Plus shape */
+TEST(polyfill2d, PlusShape)
+{
+ const float poly[][2] = {
+ {1, 0}, {2, 0}, {2, 1}, {3, 1}, {3, 2}, {2, 2}, {2, 3}, {1, 3}, {1, 2}, {0, 2}, {0, 1}, {1, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Star shape */
+TEST(polyfill2d, StarShape)
+{
+ const float poly[][2] = {
+ {4, 0}, {5, 3}, {8, 4}, {5, 5}, {4, 8}, {3, 5}, {0, 4}, {3, 3}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* U shape */
+TEST(polyfill2d, UShape)
+{
+ const float poly[][2] = {
+ {1, 0}, {2, 0}, {3, 1}, {3, 3}, {2, 3}, {2, 1}, {1, 1}, {1, 3}, {0, 3}, {0, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Spiral */
+TEST(polyfill2d, Spiral)
+{
+ const float poly[][2] = {
+ {1, 0}, {4, 0}, {5, 1}, {5, 4}, {4, 5}, {1, 5}, {0, 4}, {0, 3},
+ {1, 2}, {2, 2}, {3, 3}, {1, 3}, {1, 4}, {4, 4}, {4, 1}, {0, 1}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Test case from http:# www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml */
+TEST(polyfill2d, TestFlipCode)
+{
+ const float poly[][2] = {
+ {0, 6}, {0, 0}, {3, 0}, {4, 1}, {6, 1}, {8, 0}, {12, 0}, {13, 2},
+ {8, 2}, {8, 4}, {11, 4}, {11, 6}, {6, 6}, {4, 3}, {2, 6}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Self-intersection */
+TEST(polyfill2d, SelfIntersect)
+{
+ const float poly[][2] = {{0, 0}, {1, 1}, {2, -1}, {3, 1}, {4, 0}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, true);
+}
+
+/* Self-touching */
+TEST(polyfill2d, SelfTouch)
+{
+ const float poly[][2] = {
+ {0, 0}, {4, 0}, {4, 4}, {2, 4}, {2, 3}, {3, 3}, {3, 1}, {1, 1}, {1, 3}, {2, 3}, {2, 4}, {0, 4}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Self-overlapping */
+TEST(polyfill2d, SelfOverlap)
+{
+ const float poly[][2] = {
+ {0, 0}, {4, 0}, {4, 4}, {1, 4}, {1, 3}, {3, 3}, {3, 1}, {1, 1}, {1, 3}, {3, 3}, {3, 4}, {0, 4}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, true);
+}
+
+/* Test case from http:# www.davdata.nl/math/polygons.html */
+TEST(polyfill2d, TestDavData)
+{
+ const float poly[][2] = {
+ {190, 480}, {140, 180}, {310, 100}, {330, 390}, {290, 390}, {280, 260}, {220, 260}, {220, 430}, {370, 430},
+ {350, 30}, {50, 30}, {160, 560}, {730, 510}, {710, 20}, {410, 30}, {470, 440}, {640, 410}, {630, 140},
+ {590, 140}, {580, 360}, {510, 370}, {510, 60}, {650, 70}, {660, 450}, {190, 480}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Issue 815, http:# code.google.com/p/libgdx/issues/detail?id=815 */
+TEST(polyfill2d, Issue815)
+{
+ const float poly[][2] = {
+ {-2.0f, 0.0f}, {-2.0f, 0.5f}, {0.0f, 1.0f}, {0.5f, 2.875f},
+ {1.0f, 0.5f}, {1.5f, 1.0f}, {2.0f, 1.0f}, {2.0f, 0.0f}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Issue 207, comment #1, http:# code.google.com/p/libgdx/issues/detail?id=207#c1 */
+TEST(polyfill2d, Issue207_1)
+{
+ const float poly[][2] = {
+ {72.42465f, 197.07095f}, {78.485535f, 189.92776f}, {86.12059f, 180.92929f}, {99.68253f, 164.94557f},
+ {105.24325f, 165.79604f}, {107.21862f, 166.09814f}, {112.41958f, 162.78253f}, {113.73238f, 161.94562f},
+ {123.29477f, 167.93805f}, {126.70667f, 170.07617f}, {73.22717f, 199.51062f}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, true);
+}
+
+/* Issue 207, comment #11, http:# code.google.com/p/libgdx/issues/detail?id=207#c11 */
+/* Also on issue 1081, http:# code.google.com/p/libgdx/issues/detail?id=1081 */
+TEST(polyfill2d, Issue207_11)
+{
+ const float poly[][2] = {
+ {2400.0f, 480.0f}, {2400.0f, 176.0f}, {1920.0f, 480.0f}, {1920.0459f, 484.22314f},
+ {1920.1797f, 487.91016f}, {1920.3955f, 491.0874f}, {1920.6875f, 493.78125f}, {1921.0498f, 496.01807f},
+ {1921.4766f, 497.82422f}, {1921.9619f, 499.22607f}, {1922.5f, 500.25f}, {1923.085f, 500.92236f},
+ {1923.7109f, 501.26953f}, {1924.3721f, 501.31787f}, {1925.0625f, 501.09375f}, {1925.7764f, 500.62354f},
+ {1926.5078f, 499.9336f}, {1927.251f, 499.0503f}, {1928.0f, 498.0f}, {1928.749f, 496.80908f},
+ {1929.4922f, 495.5039f}, {1930.2236f, 494.11084f}, {1930.9375f, 492.65625f}, {1931.6279f, 491.1665f},
+ {1932.2891f, 489.66797f}, {1932.915f, 488.187f}, {1933.5f, 486.75f}, {1934.0381f, 485.3833f},
+ {1934.5234f, 484.11328f}, {1934.9502f, 482.9663f}, {1935.3125f, 481.96875f}, {1935.6045f, 481.14697f},
+ {1935.8203f, 480.52734f}, {1935.9541f, 480.13623f}, {1936.0f, 480.0f}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407 */
+TEST(polyfill2d, Issue1407)
+{
+ const float poly[][2] = {
+ {3.914329f, 1.9008259f}, {4.414321f, 1.903619f}, {4.8973203f, 1.9063174f}, {5.4979978f, 1.9096732f}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407, */
+/* with an additional point to show what is happening. */
+TEST(polyfill2d, Issue1407_pt)
+{
+ const float poly[][2] = {
+ {3.914329f, 1.9008259f}, {4.414321f, 1.903619f}, {4.8973203f, 1.9063174f}, {5.4979978f, 1.9096732f}, {4, 4}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Simplified from Blender bug T40777 */
+TEST(polyfill2d, IssueT40777_colinear)
+{
+ const float poly[][2] = {
+ {0.7, 0.37}, {0.7, 0}, {0.76, 0}, {0.76, 0.4}, {0.83, 0.4}, {0.83, 0}, {0.88, 0}, {0.88, 0.4},
+ {0.94, 0.4}, {0.94, 0}, {1, 0}, {1, 0.4}, {0.03, 0.62}, {0.03, 0.89}, {0.59, 0.89}, {0.03, 1},
+ {0, 1}, {0, 0}, {0.03, 0}, {0.03, 0.37}};
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
+
+/* Blender bug T41986 */
+TEST(polyfill2d, IssueT41986_axis_align)
+{
+ const float poly[][2] = {
+ {-0.25, -0.07}, {-0.25, 0.27}, {-1.19, 0.14}, {-0.06, 0.73}, {0.17, 1.25}, {-0.25, 1.07},
+ {-0.38, 1.02}, {-0.25, 0.94}, {-0.40, 0.90}, {-0.41, 0.86}, {-0.34, 0.83}, {-0.25, 0.82},
+ {-0.66, 0.73}, {-0.56, 1.09}, {-0.25, 1.10}, {0.00, 1.31}, {-0.03, 1.47}, {-0.25, 1.53},
+ {0.12, 1.62}, {0.36, 1.07}, {0.12, 0.67}, {0.29, 0.57}, {0.44, 0.45}, {0.57, 0.29},
+ {0.66, 0.12}, {0.68, 0.06}, {0.57, -0.36}, {-0.25, -0.37}, {0.49, -0.74}, {-0.59, -1.21},
+ {-0.25, -0.15}, {-0.46, -0.52}, {-1.08, -0.83}, {-1.45, -0.33}, {-1.25, -0.04}};
+
+ TEST_POLYFILL_TEMPLATE_STATIC(poly, false);
+}
diff --git a/tests/gtests/blenlib/BLI_ressource_strings.h b/tests/gtests/blenlib/BLI_ressource_strings.h
new file mode 100644
index 00000000000..d7002d748c9
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_ressource_strings.h
@@ -0,0 +1,602 @@
+/* Apache License, Version 2.0 */
+
+#ifndef __BLENDER_TESTING_BLI_RESSOURCE_STRING_H__
+#define __BLENDER_TESTING_BLI_RESSOURCE_STRING_H__
+
+const char words10k[] =
+"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam auctor ultrices purus tincidunt mollis. Vestibulum "
+"tincidunt imperdiet molestie. Vivamus posuere, risus ut mollis rutrum, lacus nulla mollis velit, consectetur auctor "
+"erat est in odio. Proin quis lobortis ex. Ut id quam lacus. Morbi ultrices orci quis sem suscipit tincidunt. Nullam "
+"ut molestie justo, vulputate placerat diam. Nunc tincidunt auctor venenatis. Phasellus placerat, odio ac dictum "
+"pretium, nisi odio tristique sem, sit amet hendrerit odio tortor eu felis. Duis placerat tristique neque, sit amet "
+"ornare nulla fermentum vel. Vivamus vitae rhoncus ante. Sed a dolor mauris. Nullam bibendum vehicula semper. Duis ut "
+"commodo nibh. Nulla sit amet eros feugiat, accumsan nisl a, ornare quam. In non magna orci. Curabitur finibus tempus "
+"semper. Aliquam fringilla arcu consectetur blandit vestibulum. Mauris mollis est arcu. Praesent pellentesque lacus "
+"bibendum massa commodo commodo. Aenean facilisis lobortis varius. Ut semper ullamcorper dui, at pellentesque felis. "
+"Duis accumsan sapien ut malesuada lacinia. Praesent elementum venenatis arcu in mattis. Nunc sagittis mauris risus, "
+"quis rutrum nisi egestas quis. Maecenas pharetra posuere auctor. Suspendisse mollis sollicitudin elit, id cursus "
+"massa bibendum eu. Integer tincidunt dolor non porttitor tempus. Donec lacinia sapien eu enim feugiat suscipit non "
+"malesuada diam. Suspendisse nec convallis elit. Nulla eu augue ultrices, consequat lorem at, malesuada magna. "
+"Aliquam sed tempor ipsum. Sed hendrerit nec lectus et pharetra. In felis sem, cursus at nunc in, tristique convallis "
+"purus. Praesent augue turpis, porttitor consequat risus ornare, laoreet commodo dui. Nulla congue ultrices sapien a "
+"cursus. Nulla facilisi. Integer lacinia enim sodales sem mattis, sit amet egestas lectus tincidunt. Ut quis nisl ut "
+"ex luctus fermentum quis et diam. Maecenas lectus leo, hendrerit eu facilisis et, mattis ut sem. Duis imperdiet nisl "
+"vitae urna consequat suscipit. Suspendisse sed viverra massa, dapibus condimentum sem. Morbi suscipit congue odio. "
+"Nullam eleifend fringilla nisl et semper. Sed eu neque ante. Sed eget viverra urna. Duis tempor laoreet interdum. "
+"Nunc fringilla aliquet urna sit amet commodo. Curabitur non orci nec libero egestas ullamcorper nec nec velit. Nam "
+"vitae ligula lobortis, vehicula nulla id, lacinia urna. Morbi id dignissim eros. Etiam eu risus in sem vestibulum "
+"dapibus ut mollis sem. Quisque ultricies pulvinar maximus. Proin risus turpis, auctor eget molestie nec, molestie a "
+"ipsum. Donec dapibus dui in lorem rhoncus, non rutrum neque convallis. Donec at tincidunt turpis, nec scelerisque "
+"lorem. Donec ac sapien mi. Sed commodo efficitur tempus. Maecenas eu lobortis diam. Phasellus enim nulla, ornare ac "
+"laoreet egestas, vestibulum ac arcu. Pellentesque ultrices mauris sem, a iaculis diam tristique id. Proin sed "
+"facilisis mauris. Aliquam nibh ex, varius in consequat laoreet, sollicitudin id diam. Vivamus semper ultrices sem "
+"non tempor. Sed hendrerit maximus malesuada. In ex orci, elementum non magna eget, congue sagittis tellus. Donec "
+"malesuada sem leo, quis malesuada risus blandit et. Praesent porta malesuada metus eget pretium. Vestibulum "
+"venenatis tempor tellus at varius. Donec mauris arcu, elementum vitae aliquet nec, ullamcorper vitae neque. Nunc eu "
+"viverra justo, sit amet viverra elit. Proin urna elit, luctus ut placerat quis, blandit vitae diam. Vestibulum id "
+"fringilla enim. Ut eleifend augue ante, ac euismod sapien luctus sit amet. Pellentesque mattis tortor ac rutrum "
+"malesuada. Sed et nulla id metus faucibus condimentum. Vestibulum cursus posuere vestibulum. Proin auctor arcu erat, "
+"quis porta sem dignissim a. Donec sed finibus ante. Integer porttitor pretium nunc, eu semper elit. Nam sit amet "
+"ornare urna. Suspendisse porta augue id massa luctus maximus. Fusce tellus ligula, finibus sed lacus eget, tristique "
+"mollis libero. Vivamus velit diam, faucibus vel fringilla vitae, ornare id lacus. Pellentesque vel sem quis nunc "
+"semper porta ut sit amet sapien. Integer nec leo at tortor ullamcorper pulvinar at ut ante. Fusce velit nisl, "
+"fermentum in tempus ac, gravida ac tellus. In aliquet sollicitudin erat, non vestibulum diam aliquam in. Duis purus "
+"justo, aliquet ut libero vel, egestas mollis nibh. Praesent sed tempor mauris, vel tempor augue. Morbi eu eros vel "
+"velit condimentum porttitor nec sit amet odio. Nunc suscipit risus at ex aliquam, in pretium mi maximus. Mauris "
+"sollicitudin sit amet arcu luctus maximus. Curabitur vehicula condimentum porta. Nunc consequat vitae urna vel "
+"gravida. Vivamus vitae mattis augue, sit amet blandit enim. Phasellus odio leo, cursus eget lacus sit amet, "
+"facilisis mattis tortor. Duis venenatis ante libero, eu condimentum urna viverra fermentum. Suspendisse libero leo, "
+"pretium eu leo at, imperdiet ultricies nunc. Fusce ante neque, feugiat id lacus sed, fringilla suscipit ligula. "
+"Phasellus cursus malesuada urna, vel ullamcorper massa suscipit vitae. In eu bibendum augue. Duis auctor posuere "
+"turpis nec vestibulum. Vestibulum nec dui in mi consequat auctor sed at nisl. Suspendisse tellus elit, congue ut "
+"facilisis vel, ornare id mauris. Integer rutrum fermentum neque, vitae pharetra metus consectetur in. Duis vitae "
+"lacus scelerisque, rhoncus nisl id, sagittis elit. Praesent lacinia libero ac ultricies tempus. Etiam ut maximus "
+"sapien. Maecenas sit amet ante auctor, feugiat diam non, vulputate diam. Nulla facilisi. Vestibulum id augue velit. "
+"Donec at elementum urna. Morbi elementum nunc in neque ornare, sit amet tempor mauris vulputate. Nunc mauris mauris, "
+"lobortis non nibh sed, gravida sollicitudin nunc. Nunc vel dolor non augue venenatis semper vitae non turpis. "
+"Praesent mattis elit eu interdum porttitor. Etiam quis magna magna. Praesent a ipsum est. Aenean at ligula vel leo "
+"faucibus pulvinar sed eget mauris. Nam accumsan blandit nibh, nec tincidunt nisl eleifend sit amet. Etiam ornare, "
+"arcu nec dictum volutpat, nulla orci porttitor orci, vel venenatis mi massa at erat. Maecenas eget accumsan nisl, "
+"quis ullamcorper turpis. Pellentesque sit amet mi aliquet, feugiat felis in, dictum urna. Cras nulla leo, congue vel "
+"consequat gravida, aliquet a nulla. Nulla commodo, nisi eu ultricies feugiat, justo velit tempor ligula, a tincidunt "
+"nisi tellus ut sapien. Sed eget ornare magna. Cras ut vehicula sapien. Quisque id malesuada urna, vitae congue ante. "
+"Donec nec leo pretium, finibus nibh a, porta lectus. Fusce arcu tellus, tempor semper sem id, aliquam fringilla "
+"ipsum. Ut massa ante, placerat quis sapien quis, sollicitudin blandit turpis. Aenean posuere ullamcorper massa. Nam "
+"faucibus egestas arcu. Vivamus vehicula auctor diam, eu placerat diam ullamcorper at. Nulla eu consequat elit, vel "
+"semper turpis. Curabitur rhoncus nunc vel vestibulum interdum. Nam augue neque, pharetra vel nisi dignissim, "
+"vehicula dapibus risus. Cras eget mattis nisi. Sed tempor posuere gravida. Proin sagittis a nisl eget gravida. "
+"Curabitur viverra dapibus arcu, sit amet rutrum nibh fringilla euismod. Donec vitae risus non lorem facilisis cursus "
+"eu eu quam. Donec quis lacus blandit, consectetur elit ut, sagittis ligula. Etiam dapibus ex sit amet elit commodo "
+"finibus. Suspendisse non finibus felis, non cursus libero. Vivamus semper aliquet velit vel elementum. Phasellus "
+"dictum, tortor id sagittis ultrices, ex dui porttitor tortor, nec mattis dolor sem nec mi. Ut aliquam consequat eros "
+"sit amet mollis. Nullam mollis venenatis porttitor. Donec sit amet velit at velit luctus auctor dictum in neque. Ut "
+"vulputate ultricies mollis. Pellentesque elementum augue dolor, non varius ligula tristique ac. Nullam eget mauris "
+"urna. Integer elementum eleifend pulvinar. Morbi gravida ante eget ornare faucibus. Mauris pulvinar consequat nunc "
+"vel accumsan. Curabitur egestas urna elit, ut accumsan magna dictum in. Nam neque mi, ornare sed leo at, tempor "
+"vulputate nunc. Nunc dignissim mauris id dui iaculis fringilla. Praesent malesuada tellus in dapibus feugiat. "
+"Vivamus posuere, nisi et consequat euismod, lorem augue iaculis velit, eget iaculis neque quam eu mi. Nullam ac "
+"hendrerit felis, non elementum ipsum. Aliquam erat volutpat. Proin vel molestie felis. Nullam luctus vel ante nec "
+"facilisis. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Duis et metus "
+"justo. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut tristique sit amet elit et congue. Aenean "
+"quis elementum enim, vitae pharetra sem. Vestibulum vel finibus nisl, at consequat eros. In vitae mollis lacus, et "
+"pharetra elit. Mauris varius sapien quis tincidunt blandit. Proin non semper nibh. Aliquam non elit id felis laoreet "
+"interdum eget a risus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. "
+"Suspendisse nisl tellus, mollis id erat vel, hendrerit volutpat nunc. Quisque scelerisque cursus tellus, nec "
+"placerat quam imperdiet in. Sed porttitor arcu vel ligula finibus, a vestibulum enim ultrices. Fusce imperdiet augue "
+"eget est vehicula porttitor. Quisque convallis odio vitae lorem porttitor iaculis. Ut dictum velit ac tortor "
+"lobortis ultrices. Vestibulum tincidunt vestibulum mauris, at fermentum elit imperdiet nec. Nunc finibus ornare "
+"lorem vel malesuada. Praesent arcu turpis, pulvinar sit amet accumsan quis, tincidunt vel justo. Pellentesque "
+"volutpat nec enim sit amet pulvinar. Nam eu libero dignissim, volutpat elit ut, semper tortor. Morbi pellentesque "
+"nisl lectus. In vel tellus sed sem luctus lobortis ut nec diam. Phasellus id semper sem. Phasellus in purus "
+"consequat, rhoncus mi mollis, finibus ligula. Fusce feugiat dictum consequat. Mauris egestas, est ut euismod "
+"consequat, arcu dui dignissim quam, pharetra dignissim orci dolor quis nisl. Nunc dapibus blandit urna non feugiat. "
+"Suspendisse non maximus augue. Quisque ut orci aliquet, vulputate massa eget, mattis diam. Etiam efficitur "
+"consectetur viverra. Nulla massa augue, elementum at turpis et, cursus ultricies risus. Suspendisse vel nibh "
+"placerat, imperdiet elit et, viverra ligula. Donec lorem lorem, hendrerit nec aliquam sit amet, scelerisque sit amet "
+"massa. Mauris convallis ullamcorper tortor sed malesuada. Fusce ultricies a turpis eu ornare. Suspendisse potenti. "
+"Sed non nulla condimentum, vulputate nisi nec, tincidunt arcu. Morbi erat leo, lobortis id odio ac, hendrerit "
+"sodales sem. Ut malesuada, lectus at posuere molestie, orci metus vehicula justo, mattis tincidunt arcu risus quis "
+"odio. Fusce non sem sed nisi consectetur finibus vitae quis diam. Vivamus a lacinia nisl. Praesent tempus nunc "
+"gravida, lacinia lacus in, lobortis massa. Aliquam gravida consequat nisi at fringilla. Quisque tortor tortor, "
+"tincidunt cursus lorem eget, ultrices ultricies lacus. Phasellus mattis iaculis elit, eget mattis nisl bibendum sed. "
+"Integer faucibus gravida nisl, ac consequat ex tempor at. Sed tempus elementum vestibulum. Suspendisse vitae enim "
+"semper, pulvinar diam eget, suscipit turpis. Maecenas ultricies, diam sed consectetur sagittis, diam sem cursus "
+"nisl, nec aliquet tellus augue quis ipsum. Cras vel lorem convallis, mattis risus at, placerat massa. Curabitur vel "
+"rutrum ligula. Quisque in nibh libero. Pellentesque diam tellus, consectetur eget quam ac, faucibus imperdiet odio. "
+"Sed tortor nulla, scelerisque non turpis nec, fringilla bibendum est. Etiam a urna eget erat tincidunt ultrices. "
+"Maecenas lorem odio, volutpat nec ligula id, hendrerit aliquam nulla. Aenean congue lacinia fermentum. Suspendisse "
+"sed interdum lacus. Fusce scelerisque posuere sagittis. Ut at semper tellus. Donec condimentum orci nunc, non "
+"fermentum purus volutpat eget. Maecenas elementum dapibus ante, eu suscipit quam imperdiet ut. Integer non congue "
+"elit. Sed venenatis, turpis varius commodo euismod, libero magna fringilla lacus, quis venenatis velit lectus sed "
+"augue. Morbi gravida orci odio, ut ornare massa sollicitudin a. Donec convallis mi et sapien tempor, non dapibus "
+"dolor fringilla. Aenean euismod rutrum turpis, et facilisis orci porttitor eu. Suspendisse in neque leo. Nulla "
+"facilisi. Etiam mollis orci nisl, quis scelerisque metus efficitur vehicula. Nam porta molestie tortor, sit amet "
+"consectetur leo vestibulum vel. Pellentesque a volutpat augue. Maecenas vel elementum ex, eget elementum leo. "
+"Curabitur at maximus metus, quis porttitor orci. Praesent auctor commodo elit, a dapibus tortor volutpat et. "
+"Praesent dictum posuere dolor sit amet molestie. Sed viverra augue nec eros mattis blandit. In quis sodales dolor. "
+"Donec sed purus ex. Fusce erat magna, efficitur ac tempus ac, lacinia quis augue. Aliquam porta efficitur est vel "
+"placerat. Phasellus egestas vel nunc eu consequat. Maecenas ligula arcu, molestie ut dui ut, ornare finibus felis. "
+"Duis condimentum non augue ut posuere. Aenean mattis eros ut ligula ornare finibus. Aliquam feugiat ut turpis a "
+"feugiat. Vestibulum eget sollicitudin orci, nec fermentum justo. Praesent efficitur est a metus bibendum, eget "
+"feugiat diam suscipit. Suspendisse sit amet ipsum ut purus feugiat pretium. Morbi nisl risus, ultricies sit amet "
+"ullamcorper euismod, commodo eu libero. Aenean fringilla ipsum nec orci rutrum aliquet. Aenean lacus ante, eleifend "
+"eu eleifend fringilla, elementum ac justo. Vestibulum tincidunt interdum lectus sit amet fermentum. Etiam rhoncus eu "
+"ante lacinia sagittis. Maecenas iaculis ut erat quis feugiat. Maecenas sed est vel tellus bibendum rutrum volutpat "
+"nec odio. Vivamus euismod augue nec purus euismod, mattis finibus nisi finibus. Donec quis ultrices massa. Quisque "
+"at nisl faucibus, facilisis tellus ut, ultricies dui. Class aptent taciti sociosqu ad litora torquent per conubia "
+"nostra, per inceptos himenaeos. Donec et arcu eros. Etiam dapibus bibendum felis eu viverra. Integer a lacus "
+"venenatis elit lacinia facilisis non non felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed "
+"ultricies augue at sapien mattis aliquam. Quisque nec semper purus. Cras auctor aliquet lacus, sed facilisis urna "
+"sollicitudin non. Vivamus eget erat purus. Sed a risus augue. Donec non sem sed sapien accumsan lacinia. Ut mauris "
+"odio, vehicula id accumsan at, tincidunt non odio. Nunc porttitor luctus ante ac cursus. Cras et dapibus ex, id "
+"pretium ligula. Proin volutpat rhoncus ex vitae venenatis. Pellentesque imperdiet, magna non tempus auctor, metus "
+"dolor scelerisque dui, id tempor purus est in risus. Suspendisse vehicula imperdiet sapien, nec pulvinar dolor "
+"ornare ac. Nulla luctus, nisl in aliquam blandit, risus orci placerat nunc, id tempus sem neque vitae leo. Aenean at "
+"elit elit. Suspendisse finibus dictum interdum. Nunc consectetur eget quam vitae egestas. Pellentesque tellus augue, "
+"aliquet at faucibus ac, imperdiet ut nulla. Maecenas quis lorem velit. Donec porta ligula et suscipit luctus. "
+"Aliquam sed pretium nunc. Nunc quis posuere tortor. Fusce in lectus nec turpis rhoncus pellentesque eu at quam. "
+"Nulla facilisi. Sed ante nulla, posuere ac ullamcorper vel, rhoncus vitae nisl. Nam non pellentesque arcu. Vivamus "
+"nibh leo, pellentesque a mollis non, gravida ut erat. Donec purus urna, pulvinar eu iaculis blandit, rutrum eget "
+"nulla. Fusce quis fermentum diam, faucibus volutpat lorem. Maecenas aliquet nisi nisl, eget sollicitudin ipsum "
+"facilisis at. Mauris nec sapien nisi. Duis ac laoreet sapien, a condimentum nisi. Nam vitae sapien sed sem convallis "
+"ornare. Pellentesque neque diam, ullamcorper et dolor sit amet, faucibus venenatis tortor. Nunc vel erat malesuada, "
+"vulputate odio sit amet, aliquam dui. Donec tincidunt arcu ut risus laoreet, id malesuada leo ultrices. Praesent a "
+"scelerisque libero, vitae suscipit massa. Quisque faucibus mauris rhoncus turpis vestibulum rhoncus. Donec vel "
+"molestie magna. Aenean et lorem dui. Nam iaculis ante sapien, semper tincidunt tortor hendrerit id. Nulla sed orci "
+"mi. Aliquam hendrerit libero erat, ac aliquam massa rutrum non. Suspendisse eleifend, elit in aliquet hendrerit, "
+"tellus erat sodales neque, quis rhoncus tellus sem vitae est. Interdum et malesuada fames ac ante ipsum primis in "
+"faucibus. Etiam quis mauris non ipsum tristique interdum sit amet eget mi. Ut velit risus, gravida ut efficitur sit "
+"amet, commodo at diam. Sed consectetur dui porttitor quam feugiat, et auctor mauris maximus. Nullam lobortis ac mi "
+"lacinia egestas. Proin ante massa, malesuada ut nulla elementum, venenatis mollis ante. Cum sociis natoque penatibus "
+"et magnis dis parturient montes, nascetur ridiculus mus. Mauris eget gravida eros, non varius velit. Integer "
+"consectetur lectus nec arcu scelerisque, scelerisque vulputate mauris suscipit. Aliquam orci dui, faucibus et rutrum "
+"in, rhoncus quis dolor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; "
+"Maecenas ante nunc, placerat id lectus sit amet, luctus cursus ante. Nulla nec placerat arcu. Fusce ac dictum ex. "
+"Vivamus semper nulla vitae neque volutpat, auctor vestibulum arcu tempus. Pellentesque aliquam tincidunt arcu, et "
+"pharetra neque. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nunc "
+"risus augue, malesuada quis risus a, suscipit semper metus. Suspendisse ac rhoncus felis. Aliquam orci lectus, "
+"elementum at nulla at, ullamcorper pellentesque leo. Quisque nisi tellus, pharetra in pellentesque in, facilisis "
+"vitae velit. In ex ex, sagittis at dolor vel, congue ultricies velit. Duis quis gravida mi. Aenean tempor efficitur "
+"lectus. Fusce sodales, ex eu efficitur iaculis, metus sem eleifend purus, ut commodo arcu tortor eget urna. Etiam "
+"nisi nisl, malesuada convallis ex at, malesuada elementum nunc. Vivamus commodo mi id ligula tincidunt posuere. "
+"Integer eget arcu cursus, sagittis quam eu, aliquam leo. In auctor eget mauris et elementum. Aenean sagittis euismod "
+"tellus sed accumsan. Aliquam erat volutpat. Aliquam erat volutpat. Ut consectetur porta ipsum sit amet porttitor. "
+"Nam ut nunc a turpis auctor finibus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac "
+"turpis egestas. Donec non nisl condimentum, fermentum augue in, egestas libero. Pellentesque ut odio rhoncus, "
+"sollicitudin felis vitae, pellentesque est. Suspendisse tincidunt eros eget ex vestibulum elementum. Vivamus mollis "
+"scelerisque diam, quis dignissim dolor venenatis at. Ut gravida sapien vitae risus efficitur, ut auctor justo "
+"gravida. Cras arcu elit, interdum vel purus sit amet, venenatis molestie tellus. Integer consectetur tempor velit a "
+"varius. Praesent congue, massa non congue blandit, tortor purus imperdiet elit, sit amet pharetra arcu lacus egestas "
+"neque. Maecenas in erat arcu. In varius, risus vitae mollis sodales, nisi velit bibendum tortor, vitae sagittis "
+"augue tortor quis nunc. Fusce posuere dolor ac tincidunt facilisis. Phasellus in lacus diam. Fusce mattis sapien "
+"tellus, scelerisque pharetra leo eleifend nec. Cras libero diam, convallis in luctus a, iaculis a ipsum. Duis arcu "
+"leo, volutpat non mauris et, scelerisque suscipit diam. Ut vulputate placerat velit quis placerat. Duis commodo non "
+"turpis et convallis. Duis nec pulvinar metus, ac tristique leo. Fusce vehicula augue ac placerat elementum. Nulla "
+"dapibus nisi pretium lectus sodales, ac congue sapien ornare. Vestibulum sagittis orci ut purus efficitur, eu mollis "
+"libero placerat. Vestibulum ullamcorper odio non quam mollis, eget rhoncus metus eleifend. Mauris scelerisque, massa "
+"rutrum sodales malesuada, elit dolor blandit lectus, quis faucibus felis odio feugiat lacus. Nunc bibendum congue "
+"efficitur. Nunc a purus neque. In lobortis metus nisi, vel pellentesque mi facilisis sed. Donec in pretium neque, in "
+"maximus metus. Integer faucibus diam sed tristique sagittis. Nullam eget maximus leo, eget malesuada leo. Vestibulum "
+"ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean porttitor risus eget eros "
+"euismod molestie. Integer tristique tincidunt elit, non posuere libero pretium vel. Fusce dapibus, nisi nec egestas "
+"dapibus, lectus arcu maximus leo, a finibus diam arcu ut mauris. Vivamus tincidunt lectus ut augue ultrices, et "
+"cursus sem cursus. Proin in quam mauris. Maecenas vel magna dapibus, interdum ipsum mattis, posuere tortor. Cras eu "
+"massa ex. Donec eget massa vel dui gravida luctus vel a quam. Etiam eu lobortis neque. Etiam ligula dui, dictum ut "
+"turpis ac, eleifend pretium turpis. Vestibulum convallis finibus commodo. Morbi fermentum ante nunc, a rhoncus lacus "
+"ultricies quis. Suspendisse finibus quam blandit odio elementum, non efficitur diam laoreet. Cras aliquet ligula "
+"eget magna scelerisque, ut ornare nisi elementum. Duis nisl massa, suscipit id nibh a, venenatis auctor risus. Nulla "
+"luctus eget odio quis ultrices. Etiam consequat sapien ut nisl mollis cursus. Pellentesque a lacinia odio, id varius "
+"lorem. Curabitur scelerisque in urna eget pretium. Class aptent taciti sociosqu ad litora torquent per conubia "
+"nostra, per inceptos himenaeos. Sed leo metus, fermentum vitae quam ut, suscipit efficitur purus. Sed facilisis "
+"dapibus pulvinar. Cras sed eleifend mi. Sed quis nibh in sapien venenatis interdum ac nec orci. Sed non tortor urna. "
+"Nam rutrum lacinia diam id vehicula. Quisque vitae lobortis nibh, at tempor purus. Suspendisse dictum interdum nisi, "
+"quis maximus ipsum commodo tempus. Nulla semper congue gravida. Aenean at nibh in eros aliquam egestas. Nulla "
+"fermentum efficitur laoreet. Donec non lorem nec augue porttitor cursus eu in quam. Aenean laoreet quam neque, at "
+"tempus nisi ultrices id. Quisque in diam lacinia nulla scelerisque rhoncus vitae eget nulla. Donec vel est metus. "
+"Nullam suscipit odio eu enim lacinia facilisis eget in tellus. Vestibulum vehicula risus nec odio consectetur, a "
+"cursus massa imperdiet. Duis facilisis felis quis nunc mattis, nec volutpat libero tempor. Nulla nec leo sed tellus "
+"maximus lobortis. Suspendisse at urna nibh. Vestibulum eget turpis nisl. Donec scelerisque neque auctor erat tempor "
+"elementum sed id lacus. Sed metus nulla, dictum non luctus vel, suscipit et ex. Quisque laoreet sapien non neque "
+"iaculis, at aliquam massa viverra. Nullam nibh diam, imperdiet eu nunc sed, congue cursus leo. Morbi tristique diam "
+"metus, at faucibus magna mollis at. Sed eget nibh nunc. Nam nec elementum sem, sit amet tincidunt lorem. In viverra "
+"elit et interdum fermentum. Integer imperdiet orci ac justo molestie ullamcorper. Pellentesque fringilla tortor "
+"erat, scelerisque maximus nisl sollicitudin a. Integer nisi elit, pharetra eget lacinia non, congue sit amet ex. "
+"Phasellus tempus suscipit ultrices. Quisque ac nibh dignissim erat bibendum cursus vel a enim. Curabitur a augue sit "
+"amet lorem pharetra feugiat. Donec euismod, massa at venenatis bibendum, elit libero pellentesque velit, eget congue "
+"metus risus a enim. Aenean pretium vestibulum enim, sit amet vulputate urna auctor vitae. Praesent porttitor erat eu "
+"mi cursus venenatis. Maecenas ut ultrices neque, ac feugiat libero. Nulla finibus sit amet sem in auctor. Nam "
+"fermentum maximus ex, et consequat velit lobortis id. Aliquam eu feugiat est. Donec quis leo ex. Suspendisse "
+"convallis eget nulla eu aliquet. Quisque aliquet tortor vitae ipsum fermentum tristique. Sed convallis rutrum augue, "
+"ac viverra est pharetra quis. Ut porttitor magna massa, placerat maximus lectus scelerisque quis. Sed viverra urna "
+"in neque feugiat rhoncus. Donec ut viverra odio, laoreet dignissim dui. Aenean tristique feugiat diam vel luctus. "
+"Cras sit amet condimentum neque, ut faucibus ante. Aenean vitae elit id est laoreet efficitur in sit amet magna. "
+"Praesent ante felis, blandit id nisl ut, porta fringilla orci. Aenean vel accumsan metus, vel vehicula metus. Nulla "
+"placerat nibh et auctor convallis. Maecenas magna metus, pretium ac sodales ac, eleifend quis eros. Praesent "
+"volutpat quam a pulvinar pharetra. Sed arcu dolor, aliquet nec magna in, faucibus consequat lorem. In tincidunt, ex "
+"a finibus rutrum, metus dui fringilla ex, ac mollis elit leo eget augue. Nunc vehicula facilisis nibh, quis "
+"ultricies sem. Praesent nulla est, finibus in lorem in, mattis placerat urna. Proin hendrerit risus nunc, id congue "
+"ex posuere id. Aenean ullamcorper tortor quis lorem consectetur, et euismod leo fermentum. Praesent vulputate congue "
+"lectus sit amet pulvinar. Vestibulum vel vestibulum quam, in convallis diam. Maecenas sollicitudin magna odio, eget "
+"mollis purus posuere eu. Curabitur molestie mattis ligula, a maximus dui fermentum ut. Fusce justo velit, eleifend "
+"ut tellus vitae, volutpat maximus risus. Pellentesque suscipit mauris non purus placerat porta. Nunc in malesuada "
+"mi, vel bibendum felis. Aenean pretium nunc id efficitur porttitor. Mauris malesuada, tortor sit amet blandit "
+"tincidunt, tellus est ullamcorper diam, sit amet aliquet ex velit interdum quam. In hac habitasse platea dictumst. "
+"Sed vitae est eu elit posuere mattis nec a mauris. Morbi id ligula sed nunc sagittis finibus vitae eu nisi. Cras "
+"dignissim sagittis tellus a suscipit. Nunc semper erat nec libero vestibulum, at mattis purus scelerisque. "
+"Pellentesque egestas volutpat eleifend. Nullam venenatis erat id diam venenatis, sed rhoncus felis hendrerit. Nullam "
+"luctus facilisis risus. Mauris sed urna nisi. Ut tempus feugiat metus. Integer at purus velit. Praesent neque felis, "
+"pellentesque vitae sem nec, tempor commodo urna. Morbi malesuada ante sit amet purus tincidunt pellentesque. Aenean "
+"commodo lectus sit amet dignissim hendrerit. Phasellus auctor tellus ligula, eu ultrices ex egestas non. Mauris eget "
+"nisl dictum, scelerisque sapien et, dapibus felis. Aenean in dignissim leo. Sed semper, ex at euismod molestie, ex "
+"odio ullamcorper nisi, et facilisis lectus eros non magna. In hac habitasse platea dictumst. Pellentesque sed "
+"maximus mauris. Cras luctus dapibus nunc, sit amet suscipit dui viverra nec. Donec gravida tortor porttitor orci "
+"malesuada porttitor. Nunc condimentum eu libero sit amet varius. Curabitur mollis urna eu porta tincidunt. Nullam "
+"ultricies magna libero, et dapibus tellus tempus eu. Nullam pretium lectus nec iaculis pretium. Maecenas at arcu "
+"lobortis, ornare ante nec, euismod metus. Pellentesque volutpat tellus nulla. Aenean mattis efficitur velit vitae "
+"blandit. Duis vel egestas eros. Pellentesque aliquam placerat elit, eu congue sem ullamcorper sit amet. Ut erat "
+"nisl, luctus vitae pellentesque ut, tristique eu odio. Pellentesque nec fermentum ex, rhoncus varius dui. Mauris "
+"lobortis nunc nec dui volutpat consequat. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur "
+"ridiculus mus. Aliquam dignissim purus sed ligula pretium placerat. In vestibulum ultricies mauris. Curabitur "
+"aliquet lorem quis libero auctor, ut rhoncus purus lobortis. Nulla elementum erat nec rhoncus posuere. Integer "
+"faucibus quam sed elementum fringilla. In in lobortis sapien, nec commodo tortor. Aenean euismod ipsum nisi, vitae "
+"fringilla leo imperdiet ut. Donec a semper odio, et tempor magna. Cras cursus vel augue quis egestas. Nam nec tortor "
+"blandit, mattis quam imperdiet, finibus quam. Pellentesque tincidunt eros urna, ut tristique diam faucibus "
+"condimentum. Ut dictum risus mi, non sollicitudin turpis facilisis sit amet. Morbi finibus scelerisque mattis. Fusce "
+"vel tempor purus, nec pharetra augue. Curabitur dapibus, orci eu consectetur ultrices, diam mauris sodales urna, non "
+"euismod diam lacus luctus risus. Mauris commodo accumsan sapien. Proin vel blandit sapien. Donec porta tortor vel "
+"nibh faucibus molestie. Pellentesque placerat justo erat, vitae tristique felis fringilla eget. Quisque facilisis "
+"justo at orci lobortis, ut commodo diam egestas. Etiam non tristique nisl. Cras varius, massa a sollicitudin ornare, "
+"turpis arcu fringilla leo, non euismod ligula arcu id lacus. Suspendisse potenti. Morbi pharetra dolor eget porta "
+"tristique. Nullam sem tortor, lobortis eget hendrerit a, efficitur sit amet sapien. Fusce sit amet condimentum odio, "
+"aliquet rutrum velit. Morbi vel rhoncus ante. In blandit eros ut lectus varius, quis tempor arcu iaculis. In massa "
+"leo, venenatis nec lobortis non, pulvinar non nunc. Nunc vehicula, erat vitae placerat eleifend, eros ipsum "
+"consectetur odio, eu ornare velit mauris nec sapien. Integer a consequat libero. Quisque velit augue, blandit eu "
+"luctus sit amet, laoreet sit amet odio. Etiam in enim lacus. Interdum et malesuada fames ac ante ipsum primis in "
+"faucibus. In rutrum a tortor id pulvinar. Donec pretium lorem sed sem eleifend fringilla. Fusce sollicitudin ac "
+"ligula eget pharetra. Sed cursus diam non sem ullamcorper efficitur. Vivamus congue ligula iaculis justo iaculis "
+"elementum. Integer tempor nisl arcu, ut tincidunt erat vestibulum et. Suspendisse rutrum aliquet eros non "
+"pellentesque. Mauris laoreet, diam id tincidunt faucibus, risus velit venenatis risus, in venenatis justo diam et "
+"orci. Etiam pulvinar pulvinar nisi, id efficitur erat vulputate ut. Sed suscipit sodales ante, a blandit orci "
+"maximus vel. Vestibulum at aliquet orci. Proin tincidunt nisi quis eros consequat consectetur. Praesent congue "
+"lobortis laoreet. Donec imperdiet risus erat, eu volutpat justo posuere id. Fusce placerat sollicitudin eros vitae "
+"tincidunt. Sed orci ante, ultricies sed dapibus vel, sagittis ac massa. Pellentesque vel mauris nec est hendrerit "
+"posuere. Integer sagittis diam sed felis facilisis ultrices. Aliquam erat volutpat. Nulla pharetra justo in ipsum "
+"dapibus, nec viverra nunc euismod. Nulla massa ante, euismod at interdum vel, dapibus ut ex. Etiam consequat mauris "
+"a suscipit lobortis. Donec commodo convallis velit, eget commodo urna vulputate ac. Sed molestie vel dui ut feugiat. "
+"Donec orci purus, placerat vitae egestas sed, sodales nec ex. Sed egestas turpis non malesuada semper. Donec et mi a "
+"nisi volutpat sagittis. Suspendisse potenti. Phasellus mollis sapien ac tellus imperdiet tempus. Praesent nec sapien "
+"sit amet ipsum interdum interdum non eget nunc. Aenean fringilla lorem a viverra rutrum. Donec at maximus nibh. "
+"Phasellus facilisis justo sit amet metus pharetra sagittis. Quisque mollis metus laoreet ipsum tincidunt "
+"sollicitudin. Maecenas sit amet dictum ligula. Fusce molestie iaculis dui, et gravida libero hendrerit in. Praesent "
+"euismod libero metus, vitae rhoncus velit ultrices eget. Vestibulum ac massa bibendum, gravida dolor vel, dapibus "
+"est. Etiam non elit varius, mollis purus eget, placerat velit. Nullam lectus dui, mattis at pulvinar eu, elementum "
+"et lorem. Sed vel auctor orci, nec semper neque. Nullam cursus commodo quam, in ultricies tellus rhoncus vulputate. "
+"Mauris dapibus ipsum ipsum, dapibus euismod purus pellentesque at. Nullam euismod lectus non risus consequat "
+"vulputate. Quisque finibus a turpis eu convallis. Nam magna turpis, feugiat ut urna in, tempus facilisis elit. Duis "
+"dignissim purus sagittis porttitor posuere. Suspendisse varius ligula at egestas scelerisque. Duis placerat sagittis "
+"nisi, et molestie tortor posuere condimentum. Morbi hendrerit, ante ornare tempus finibus, ex ipsum laoreet dui, vel "
+"ornare felis tortor sit amet metus. Vivamus laoreet placerat massa, non suscipit nisl faucibus eget. Vestibulum ante "
+"ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque orci lacus, vulputate cursus ex "
+"eu, porta aliquam massa. Proin dolor massa, faucibus vel rhoncus et, venenatis a nisi. Vivamus venenatis enim mi. "
+"Sed viverra augue vitae lectus lobortis vulputate. Phasellus ac ligula congue, sagittis est non, aliquet tortor. "
+"Suspendisse faucibus euismod neque, ac congue felis. Curabitur maximus neque sit amet odio varius gravida. Proin "
+"egestas nulla eget mi bibendum luctus. Ut non mollis mi. Quisque finibus, eros non lobortis interdum, diam nisi "
+"faucibus diam, non imperdiet leo velit et dolor. Nam est massa, vehicula sed diam sed, laoreet convallis nisi. Donec "
+"enim ligula, dignissim non sem ut, pulvinar cursus mi. In at dignissim nulla, ac fringilla neque. In hac habitasse "
+"platea dictumst. Quisque luctus mattis orci, consequat egestas nisi. Vivamus et metus et quam porttitor elementum. "
+"Suspendisse auctor mauris eu sollicitudin sagittis. Vivamus ac ante non augue iaculis consectetur quis quis dui. In "
+"bibendum risus tristique ligula iaculis finibus. Phasellus non ante risus. Maecenas ac leo cursus, molestie purus "
+"sed, tristique purus. Etiam sem nulla, aliquam nec laoreet nec, iaculis quis nulla. Maecenas id dui id neque "
+"venenatis gravida. Etiam vestibulum felis at diam porta ultrices. Ut finibus tortor et augue ornare, et efficitur "
+"purus scelerisque. Phasellus et ultricies arcu, vel lacinia lacus. Aenean tincidunt eleifend nunc, sit amet mattis "
+"purus venenatis sit amet. Curabitur eleifend sem nisl, et feugiat diam pharetra sit amet. Mauris ullamcorper mi vel "
+"condimentum egestas. Nulla pulvinar purus vel sagittis posuere. Nulla quis enim bibendum, iaculis quam in, tincidunt "
+"quam. Vestibulum rhoncus volutpat risus. Nulla ultricies bibendum est non malesuada. Nunc porta erat est, a "
+"tincidunt magna gravida vel. Maecenas sit amet aliquet odio. Vestibulum egestas, tortor scelerisque consectetur "
+"pharetra, nisi tellus feugiat justo, et bibendum libero mi in diam. Aliquam tempus sapien nec tristique convallis. "
+"Nullam congue, lacus quis bibendum dignissim, nisl purus molestie dolor, a tempor dolor nibh pretium tellus. In hac "
+"habitasse platea dictumst. Cras at est turpis. Nam nec lacus posuere, mattis mi eu, viverra ex. Nullam eleifend "
+"ornare orci, vel tempor tellus. Ut nec eros eget tortor tempus tristique commodo sed lorem. Donec quis scelerisque "
+"nibh, non tincidunt velit. Fusce in eleifend sapien. Nunc sodales sem ut nunc pellentesque, eget pharetra justo "
+"tempor. Proin pretium velit et vehicula interdum. Maecenas luctus venenatis tincidunt. Donec hendrerit, ligula non "
+"volutpat porta, dui ante facilisis massa, at congue orci mi sed quam. Donec lorem ipsum, malesuada quis purus in, "
+"commodo malesuada justo. Etiam luctus, lorem vel rutrum tristique, mauris urna volutpat felis, a laoreet urna nunc "
+"et neque. Morbi a diam tincidunt augue cursus commodo nec ut ligula. Maecenas ultrices purus fermentum ullamcorper "
+"aliquet. Maecenas mi enim, semper nec metus at, posuere tristique ligula. Suspendisse est elit, porta quis massa id, "
+"gravida commodo ante. Nullam maximus mauris sit amet dolor tempus posuere. Phasellus purus mi, interdum in ipsum "
+"quis, tristique venenatis dolor. Suspendisse potenti. Phasellus odio erat, varius sed aliquet vestibulum, laoreet "
+"sed mauris. Vivamus sapien erat, maximus tristique elementum ac, eleifend in enim. Morbi accumsan elementum neque, a "
+"facilisis enim laoreet non. Donec auctor condimentum fringilla. Proin id urna nec tellus maximus maximus tincidunt "
+"et libero. Integer ultricies venenatis odio, ut volutpat odio laoreet non. Donec in scelerisque justo. Integer "
+"mauris libero, fringilla vel sapien sit amet, laoreet tincidunt dolor. Nam efficitur sagittis arcu, vel lobortis dui "
+"gravida non. Curabitur lobortis feugiat finibus. Vestibulum dictum tortor nec magna fringilla blandit. Nulla "
+"facilisi. Sed cursus laoreet neque vitae pulvinar. Ut iaculis euismod ullamcorper. Nunc in hendrerit lectus, sed "
+"venenatis mi. Suspendisse et est dui. Sed elementum augue non ornare cursus. Quisque varius facilisis magna nec "
+"laoreet. Suspendisse consequat, risus sed tempus egestas, velit felis faucibus erat, eu pharetra erat nisl sed "
+"turpis. Sed ultricies ac quam id mollis. In consequat et erat vitae interdum. Pellentesque malesuada feugiat ligula "
+"eu consectetur. Vestibulum tempor mi quis purus luctus dictum. Etiam condimentum ac ligula eget imperdiet. Ut "
+"placerat, tortor eu lacinia imperdiet, enim nibh aliquam nibh, quis faucibus enim odio eu arcu. Nullam sagittis, "
+"diam a ornare congue, ipsum eros scelerisque est, sit amet sagittis nisl tellus in felis. Nam eget ornare turpis. "
+"Sed tempor ac enim a vestibulum. Pellentesque eleifend lacus non libero accumsan, ut consectetur sapien lacinia. "
+"Etiam ut arcu non mi feugiat accumsan ut sit amet risus. Donec consequat eros sapien, malesuada imperdiet justo "
+"bibendum sit amet. Nulla pretium varius lectus, in eleifend quam fringilla in. Quisque eu pretium velit. Sed eget "
+"lectus sit amet tortor blandit tempus vel at sapien. Sed at velit porta, venenatis lorem sed, dapibus arcu. Donec "
+"pellentesque tortor id massa interdum pretium. Praesent id diam quis nunc dictum finibus quis quis ipsum. Quisque "
+"consectetur risus eu elit viverra, eget laoreet odio efficitur. In congue turpis iaculis ullamcorper bibendum. Duis "
+"at elit et velit varius vulputate ut ac turpis. Nunc posuere, urna id lobortis ornare, neque ex ultricies erat, id "
+"sollicitudin ante quam sed magna. Nunc ultrices quam erat, eget dictum libero sollicitudin in. Nulla facilisi. "
+"Pellentesque eleifend risus non justo imperdiet aliquet. Donec finibus auctor ornare. Duis in arcu lacinia, "
+"fermentum tellus vel, efficitur justo. Morbi nec nunc leo. Proin lacinia erat vel elementum dapibus. Proin diam "
+"ipsum, mollis eu lobortis a, facilisis consectetur est. Vestibulum rutrum pellentesque urna, a laoreet justo dictum "
+"vitae. Nullam dictum, mi elementum dictum interdum, sem nisl fermentum est, nec mattis enim ante aliquam tortor. "
+"Phasellus eu quam magna. Vivamus augue enim, dictum in nibh non, condimentum tristique lorem. Suspendisse potenti. "
+"Sed nibh lacus, auctor ut arcu sollicitudin, posuere tempor urna. Phasellus at odio euismod ipsum congue auctor. "
+"Fusce vestibulum elementum nunc, vel feugiat nibh bibendum at. Quisque felis ligula, fermentum a metus ac, pulvinar "
+"hendrerit est. Proin vitae tincidunt purus, vestibulum eleifend ipsum. Ut rhoncus et elit ut varius. Praesent eu "
+"pharetra tellus. Suspendisse varius, dui quis efficitur fermentum, est lectus ultricies ex, a fermentum orci nunc eu "
+"lorem. Integer aliquet nunc ullamcorper lacinia elementum. In cursus tortor nisi, ut pharetra tortor venenatis eu. "
+"Duis tincidunt, libero sed varius dictum, neque velit facilisis enim, eget bibendum mi eros et nisl. Nam turpis "
+"neque, lobortis eget ante ac, tristique congue lacus. Aenean dictum vitae tortor sed tristique. Donec sodales in "
+"arcu ut tristique. Curabitur in facilisis nisi, non vulputate odio. Phasellus ut fringilla nunc, nec dapibus turpis. "
+"Sed ut erat tempor sem vulputate gravida at at dui. Aenean id dolor ante. Morbi auctor interdum nisi, id pretium "
+"eros ultrices vel. Nulla eget justo fringilla, finibus quam et, accumsan ex. In nisl neque, pharetra nec volutpat "
+"at, mattis nec odio. Nam et sapien sed libero lacinia tempor sit amet vitae turpis. Praesent vel porta lacus, porta "
+"dignissim nunc. Aenean vitae vulputate purus. Ut at elit arcu. Integer risus neque, varius ac elit maximus, "
+"ultricies sagittis nisi. Pellentesque sapien magna, malesuada tincidunt ornare sed, malesuada tempor odio. Morbi id "
+"neque velit. Pellentesque at velit sed elit eleifend auctor. Quisque tincidunt tempus justo, venenatis dapibus sem "
+"pellentesque quis. Suspendisse finibus feugiat est id consectetur. Nulla commodo, massa auctor vulputate egestas, "
+"arcu massa tincidunt leo, quis ullamcorper sapien augue in nibh. Pellentesque ultrices ligula tincidunt urna "
+"fringilla, ac ultricies eros convallis. Ut nec massa diam. Maecenas justo nulla, dapibus id justo sollicitudin, "
+"fermentum tempor dui. Vivamus laoreet auctor mi non venenatis. Nulla commodo libero ac ex volutpat tincidunt. Donec "
+"vestibulum blandit purus bibendum laoreet. Morbi in porta orci. Nam commodo ex eget diam maximus cursus. Proin "
+"bibendum quis felis eget euismod. Praesent neque neque, pulvinar eu sem non, gravida ornare tortor. Ut tortor nisi, "
+"suscipit in lectus ac, volutpat pretium nisi. Nam rutrum nec dui quis vulputate. Duis in velit enim. Fusce porttitor "
+"vitae nisi a tincidunt. Ut enim purus, venenatis ut purus ut, iaculis dignissim ex. Aliquam erat volutpat. "
+"Suspendisse potenti. Maecenas ut malesuada elit. Maecenas tellus neque, pulvinar non metus ut, viverra finibus diam. "
+"Sed ac porttitor dui. Fusce sit amet ligula metus. Integer id aliquet libero. Sed tempor nisl in porttitor "
+"ultricies. Maecenas molestie orci sed sapien molestie interdum non id felis. Nullam sagittis elementum erat in "
+"pretium. Nunc pellentesque, ex sit amet fringilla dignissim, augue quam dictum leo, eget tristique turpis mauris sed "
+"metus. Praesent vel mauris risus. Etiam eleifend metus ut risus tempor, ac ultrices dolor dictum. Nulla sagittis non "
+"urna vitae feugiat. In venenatis arcu vel finibus volutpat. Nam non bibendum magna, nec eleifend ex. Etiam sit amet "
+"nisl euismod, mattis nisi quis, commodo nisl. Nunc eget mauris vulputate, cursus neque in, hendrerit ante. Cras non "
+"nisl in nisl laoreet aliquam. Sed vestibulum, nunc vitae molestie varius, lectus justo vehicula est, nec placerat "
+"ipsum lectus quis leo. Maecenas efficitur semper eros, sed pretium arcu blandit eu. Aliquam eget purus cursus, "
+"sollicitudin augue quis, cursus purus. Maecenas sed finibus ligula. Curabitur at diam quis eros mollis semper. Nulla "
+"commodo nisi libero, id feugiat nisl tincidunt bibendum. Mauris convallis tincidunt justo eu sodales. Quisque arcu "
+"lacus, finibus sed hendrerit at, convallis ut diam. Nulla enim nulla, efficitur quis tincidunt et, pulvinar sit amet "
+"enim. Aenean mattis urna id mauris maximus tincidunt. In hac habitasse platea dictumst. Morbi ornare porta congue. "
+"Aliquam hendrerit efficitur mi at aliquet. Vivamus rutrum lectus vel turpis volutpat, consectetur congue sem "
+"consectetur. Sed rhoncus elit sed orci tincidunt, ut condimentum diam ornare. Nulla facilisi. Ut placerat et massa "
+"nec malesuada. Praesent dapibus condimentum augue, at imperdiet lacus facilisis sed. Praesent at metus nunc. Morbi "
+"accumsan eros et turpis viverra, nec sagittis odio iaculis. Aenean rhoncus, nibh a consectetur sodales, massa lorem "
+"commodo dui, sit amet consequat ex arcu eget augue. Praesent quis nibh urna. Cras eu congue ligula, in ultricies "
+"ante. Etiam interdum, est tincidunt euismod sollicitudin, lectus felis mollis ex, pretium fringilla magna lorem non "
+"libero. Fusce aliquam tellus eget sodales commodo. Sed sapien lectus, dapibus quis elit at, ultricies tincidunt "
+"eros. Nulla suscipit orci sit amet aliquam pellentesque. Cras sed eleifend ligula, quis vehicula ligula. Integer "
+"quis tortor in mauris dictum malesuada sed non turpis. Nulla faucibus quis arcu molestie vulputate. Proin fermentum "
+"tellus feugiat, imperdiet mi sit amet, tempor sem. Mauris hendrerit augue a vulputate vulputate. Vivamus sagittis at "
+"odio non venenatis. Nunc a molestie dolor. Nunc erat nisi, consequat et tristique in, blandit non tortor. Vivamus "
+"euismod bibendum augue, ut aliquam lorem mattis quis. Duis laoreet odio at justo ultricies, nec scelerisque enim "
+"euismod. Sed eu turpis a lorem cursus feugiat. Duis ultrices molestie nulla non pharetra. Morbi faucibus est auctor "
+"faucibus placerat. Donec blandit quis ex ac pulvinar. Vestibulum a consequat quam. Fusce vitae facilisis ex. Etiam a "
+"risus eu orci tincidunt interdum. Proin interdum eros nec nibh venenatis, sed luctus sapien tincidunt. In cursus, "
+"ante nec dapibus bibendum, augue tortor venenatis felis, eu aliquam erat est vitae diam. Cras lacinia placerat quam, "
+"eu finibus purus. Aenean et augue purus. Praesent efficitur ornare magna in cursus. Nunc quis tempor ante, ac "
+"accumsan ligula. Nullam elit diam, tempus in sollicitudin at, fermentum tincidunt mi. Vestibulum accumsan, nisi at "
+"rutrum scelerisque, justo mauris cursus nulla, finibus cursus nulla elit quis augue. Aliquam lacus ante, ullamcorper "
+"quis varius vitae, ullamcorper eget magna. Phasellus mollis nisl eu nulla eleifend, non tempus tellus faucibus. "
+"Curabitur molestie eros id eleifend accumsan. Suspendisse tristique sem ante, non blandit eros accumsan ac. Ut sit "
+"amet ante justo. Nam condimentum felis quis urna sagittis hendrerit. Cras condimentum est ac massa aliquet finibus. "
+"Donec faucibus malesuada fermentum. Aliquam malesuada augue vitae dolor rutrum pellentesque. Nullam vulputate "
+"rhoncus porta. Quisque vulputate dignissim felis sit amet aliquet. Nam elementum odio velit, eget fringilla mi "
+"dignissim at. Mauris mollis diam orci, vel porta risus tempor a. Nullam quis dolor volutpat, ornare est at, "
+"fermentum urna. Fusce mollis nisl a augue condimentum, eu dictum dolor posuere. Mauris et egestas sem. Sed pretium "
+"lectus laoreet velit feugiat luctus. Nullam sodales at augue vel semper. Pellentesque vehicula dictum augue, eget "
+"tristique orci interdum a. Aenean non est eleifend, tristique urna sed, elementum nunc. Sed consectetur id lorem "
+"quis mollis. Ut et blandit velit, et lobortis dolor. Quisque nec odio sed mi ullamcorper pellentesque. Ut vitae "
+"eleifend nisi, vitae dapibus est. Vivamus ornare eleifend volutpat. Sed et tincidunt nisi. Praesent maximus risus a "
+"bibendum consequat. Vestibulum quis ex vitae ante ultricies ultricies. Maecenas dictum tellus eget enim tincidunt "
+"imperdiet. Quisque vel libero gravida, mollis erat id, placerat dolor. Etiam ante eros, bibendum vitae ultricies in, "
+"rhoncus nec turpis. Pellentesque gravida nunc sit amet iaculis condimentum. Phasellus in ultricies libero, et "
+"maximus justo. Donec ut ultrices elit. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque "
+"rhoncus, nunc at iaculis dictum, magna lectus rhoncus augue, vel aliquam sem mauris in metus. Morbi commodo purus "
+"mi, ut faucibus dui luctus et. Suspendisse accumsan placerat tortor. Cras dignissim blandit leo, non tincidunt leo. "
+"Nulla euismod turpis ac malesuada aliquam. Ut ultrices bibendum elit sed elementum. Donec auctor aliquam vehicula. "
+"Mauris lacinia dignissim leo, ullamcorper egestas nibh rutrum eget. In semper sit amet libero eget ultricies. Proin "
+"et imperdiet odio. In hac habitasse platea dictumst. In hac habitasse platea dictumst. Integer sed dolor quis tortor "
+"pretium euismod at vel dolor. Donec aliquet et urna at porta. Vestibulum tincidunt eget sapien elementum mattis. "
+"Proin lacinia faucibus orci, sed eleifend augue mollis et. Vestibulum ante ipsum primis in faucibus orci luctus et "
+"ultrices posuere cubilia Curae; Cras pellentesque, dolor eget bibendum tincidunt, turpis ante pharetra tortor, quis "
+"interdum tellus tellus sit amet nisl. Nulla convallis tempus egestas. Curabitur quis condimentum metus, eu placerat "
+"metus. Nunc ligula nunc, posuere at iaculis nec, convallis id tellus. Curabitur pretium libero lorem, quis placerat "
+"nunc fringilla interdum. Vestibulum et finibus ante. Duis quis nisi neque. Curabitur ornare lorem nec ex fringilla, "
+"et porta massa consequat. Nulla malesuada turpis nec eleifend tincidunt. Praesent ultricies dolor vitae mauris "
+"lacinia tempor. Sed blandit sapien a odio scelerisque consequat. Mauris non dictum eros. Vestibulum ante ipsum "
+"primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque habitant morbi tristique senectus et "
+"netus et malesuada fames ac turpis egestas. In ut sollicitudin tellus. Suspendisse ultrices vitae erat non pharetra. "
+"Nulla pellentesque at diam venenatis sollicitudin. Vestibulum sed finibus sapien. Curabitur a metus convallis, "
+"euismod est id, iaculis nunc. Vestibulum laoreet ornare turpis. Integer rhoncus, felis nec fermentum suscipit, dui "
+"lacus sagittis ligula, vitae vestibulum urna elit aliquam est. Sed sit amet mi tortor. Suspendisse a dapibus velit. "
+"Cras eget imperdiet turpis. Maecenas at lorem condimentum, elementum augue mattis, rutrum purus. Duis imperdiet "
+"pellentesque nunc, eu tristique lectus malesuada commodo. Vivamus aliquet congue eros ac dapibus. Nunc quis "
+"porttitor odio. Nulla quis dui luctus, vestibulum enim malesuada, imperdiet elit. Donec facilisis mollis diam ut "
+"posuere. Nulla facilisi. Duis nec magna lacus. Vestibulum consequat ut tortor ut ornare. Curabitur nec felis sit "
+"amet dui finibus rutrum. Phasellus sit amet lectus nec nisl egestas posuere. Etiam nec euismod magna, vitae "
+"ullamcorper enim. Vestibulum pretium cursus semper. Cras vel lorem ut urna molestie elementum. Mauris luctus vel "
+"arcu quis egestas. Suspendisse potenti. Nullam viverra sollicitudin lacus luctus sodales. Maecenas eget diam cursus "
+"quam tincidunt ultricies vitae nec lacus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec urna "
+"sapien, porta a efficitur vitae, imperdiet vel ligula. Nulla volutpat massa sit amet est aliquet, ut iaculis tellus "
+"convallis. Sed justo tortor, sodales non nisi quis, laoreet commodo quam. Cras tempus purus a tempor malesuada. "
+"Curabitur enim nibh, viverra in enim eget, viverra euismod nunc. Mauris nunc leo, faucibus blandit condimentum nec, "
+"rutrum sit amet leo. Quisque nec tortor sed felis pretium imperdiet. Morbi lobortis, dolor nec lobortis maximus, "
+"turpis justo aliquet massa, eget aliquet nunc mauris a lectus. Phasellus dignissim, est nec luctus consequat, ex "
+"nisi euismod lacus, a viverra nulla eros et est. Suspendisse in egestas dolor. Etiam non placerat lorem. "
+"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam ut enim "
+"tristique, porta nulla quis, placerat eros. Integer eget feugiat mi, ac condimentum felis. Fusce auctor ligula ut "
+"est placerat efficitur. Nam hendrerit condimentum ante eget tincidunt. Phasellus vel convallis neque. Vivamus sit "
+"amet elit eu enim iaculis scelerisque. Donec imperdiet lacus id magna luctus, vitae dapibus quam condimentum. Donec "
+"laoreet vehicula tellus. Nullam nec neque at massa ultricies dignissim. Suspendisse potenti. Cras convallis nunc "
+"urna, a tempor metus volutpat ut. Fusce viverra lorem vitae quam ullamcorper cursus. Mauris maximus et mi eget "
+"tincidunt. Proin molestie suscipit felis at ultricies. Duis varius rhoncus metus vehicula bibendum. Aliquam "
+"consequat non tellus at aliquam. Vivamus nec turpis facilisis, dapibus lacus in, congue tortor. Curabitur at "
+"interdum mi, sed rhoncus nibh. Morbi facilisis purus laoreet, tincidunt justo sit amet, elementum lectus. Vestibulum "
+"pellentesque sem lacus, in condimentum purus consequat at. Integer pharetra rhoncus aliquam. Duis nec sem ac elit "
+"suscipit laoreet. Integer vel est commodo, feugiat sapien eget, cursus quam. Aenean elit leo, interdum a posuere "
+"nec, laoreet eu magna. Nam sit amet felis faucibus, porttitor justo eget, commodo mi. Maecenas a eleifend nibh. "
+"Donec ut ornare augue. Aliquam pellentesque aliquet eros in hendrerit. Nullam consectetur odio id lectus ullamcorper "
+"facilisis. Donec pulvinar, magna non sollicitudin commodo, erat lacus egestas massa, a egestas nibh nulla ac lorem. "
+"Maecenas at mi posuere, fringilla lectus sed, fringilla eros. Vivamus mattis at magna ac suscipit. Proin varius mi a "
+"quam efficitur ullamcorper. Curabitur venenatis turpis lacus, vitae volutpat velit ultricies sed. Sed faucibus id "
+"neque in consequat. Nulla imperdiet fermentum placerat. Donec rutrum libero ac lorem commodo pellentesque in tempor "
+"augue. Maecenas sodales cursus ex, ac elementum felis consectetur vel. Cras ante nulla, porttitor nec ex non, "
+"venenatis consectetur justo. Nam vitae enim eget augue euismod suscipit et in nulla. Morbi eu sollicitudin libero, "
+"ut lobortis purus. Pellentesque sodales tempor diam, a luctus dui vehicula tempus. Cum sociis natoque penatibus et "
+"magnis dis parturient montes, nascetur ridiculus mus. Vestibulum dignissim sagittis diam ac aliquam. Integer iaculis "
+"ac est eu molestie. Vivamus convallis arcu nec rutrum molestie. Vestibulum mollis ipsum neque. Vestibulum "
+"condimentum neque quis tellus elementum, in facilisis neque venenatis. Donec quis ultrices risus. Cras mattis felis "
+"eget erat iaculis, id scelerisque mauris pharetra. Vivamus condimentum tempor ipsum, porta commodo erat dictum ut. "
+"Fusce et ligula sed arcu tincidunt efficitur nec ut felis. Donec eu justo pellentesque, finibus diam quis, iaculis "
+"erat. Fusce a tempus urna, at fermentum est. Sed pretium orci dapibus ante laoreet, a consequat erat scelerisque. "
+"Etiam nisi tortor, vulputate quis sapien sit amet, lobortis blandit felis. Morbi urna purus, pellentesque quis orci "
+"id, suscipit consequat velit. Donec vehicula ipsum felis. Donec at elit ipsum. Fusce purus sapien, convallis quis "
+"faucibus et, tempus at dolor. Vivamus commodo sem ac congue imperdiet. Vivamus convallis eget est eu vulputate. "
+"Aliquam vehicula augue ac urna imperdiet interdum. Praesent euismod arcu quis purus vestibulum, et placerat metus "
+"hendrerit. Fusce semper lacus sit amet ligula scelerisque scelerisque. Vestibulum neque ex, aliquam non lorem a, "
+"aliquam fringilla enim. Aenean consectetur vestibulum tortor. Donec et elit consectetur, tincidunt augue feugiat, "
+"condimentum diam. In luctus tellus at massa euismod faucibus. Ut tempus dui hendrerit, vehicula ex ut, facilisis "
+"lacus. Pellentesque bibendum enim auctor, vulputate justo vel, ultricies est. Praesent interdum turpis in convallis "
+"luctus. Duis vel enim venenatis, mollis elit vitae, mattis velit. In eu posuere nibh. Duis a est est. Nam semper "
+"tincidunt nulla id dignissim. Fusce consectetur maximus eros quis posuere. Sed efficitur, enim quis ultrices "
+"eleifend, est diam commodo dui, nec euismod augue velit sit amet ante. Integer fringilla vehicula faucibus. "
+"Curabitur non placerat turpis. Integer malesuada quam eget sapien tristique aliquet. In hac habitasse platea "
+"dictumst. Cras dignissim mauris neque, in facilisis nulla pulvinar ac. Phasellus sagittis ligula non sem aliquet "
+"iaculis. Integer interdum elit in dolor vehicula, non condimentum justo pretium. Aliquam eget feugiat tellus. "
+"Suspendisse condimentum dui at erat elementum semper. Aliquam vitae cursus lorem. Ut vestibulum porttitor purus ut "
+"dapibus. Curabitur posuere nunc quis nisi rhoncus, ac mollis enim eleifend. Aenean tristique at justo ut tempor. "
+"Proin posuere condimentum arcu ac lobortis. Proin euismod posuere ipsum, nec dignissim velit eleifend gravida. "
+"Quisque quis sem mi. Proin scelerisque consequat lectus nec sodales. Fusce id sapien a erat cursus sodales. Morbi ac "
+"magna vitae lorem dictum luctus in et lacus. Morbi imperdiet mi interdum, molestie sem in, accumsan leo. Sed lacinia "
+"enim et sem egestas, a pulvinar velit ullamcorper. Aenean laoreet, erat eu viverra dictum, eros odio venenatis mi, "
+"tincidunt blandit odio mauris id augue. Donec pretium mauris nibh, ut eleifend velit auctor vitae. Morbi tincidunt "
+"lacus id ullamcorper egestas. Proin vel porttitor purus, eu fermentum dui. Aliquam a interdum mi. Aliquam ut rhoncus "
+"nibh. Morbi nulla libero, commodo quis eros eu, scelerisque gravida ligula. Aliquam sed arcu nunc. Sed egestas "
+"hendrerit orci, nec rhoncus arcu fringilla quis. Pellentesque lobortis nulla arcu. Integer aliquam vel quam sed "
+"tempor. Morbi viverra tempus risus vel convallis. Cras eget neque ex. Mauris porta, risus at rhoncus hendrerit, "
+"libero metus pharetra sapien, quis viverra tortor nunc tincidunt magna. Aenean a tellus ullamcorper, convallis urna "
+"quis, suscipit sem. Vivamus eu eleifend est. Duis venenatis metus eget ex consequat molestie. In ullamcorper a dolor "
+"vitae feugiat. Morbi ultrices vestibulum venenatis. Phasellus luctus enim id aliquet pharetra. Aenean mauris felis, "
+"finibus eu dolor at, tempor sodales diam. Sed nisl nibh, tincidunt quis fringilla vel, congue eu dui. Duis viverra "
+"justo eu sem ultricies dignissim. Morbi et sollicitudin erat. Proin id porttitor odio, et sagittis ex. Aenean "
+"laoreet leo sit amet risus vestibulum, mollis ultrices tortor porttitor. Sed vestibulum varius ligula quis accumsan. "
+"Duis fermentum, dolor iaculis condimentum tincidunt, purus nunc bibendum nibh, ac sodales tortor odio non ante. Sed "
+"leo mauris, consequat molestie quam eu, vulputate volutpat metus. Cras fringilla risus sed arcu consequat luctus. "
+"Nam malesuada, turpis at luctus blandit, velit elit fringilla metus, eu mollis odio felis id tortor. Aliquam erat "
+"tellus, pulvinar nec iaculis et, consequat sit amet diam. Sed vestibulum, leo ut vehicula suscipit, quam justo "
+"maximus lectus, nec lobortis urna tortor nec nisi. Vestibulum eget ornare arcu, sed viverra turpis. Sed posuere "
+"tellus iaculis, scelerisque dui id, convallis lectus. Aliquam sodales at mi consectetur dignissim. In fringilla, "
+"urna id placerat mattis, diam magna commodo dui, at elementum arcu elit et libero. Duis venenatis vulputate nisl "
+"congue pharetra. Fusce sapien velit, cursus a consectetur quis, auctor gravida sem. Maecenas malesuada metus quis "
+"elit congue accumsan. Vivamus scelerisque euismod malesuada. Vestibulum purus metus, tempor eget faucibus a, cursus "
+"eu arcu. Morbi dictum urna vitae velit pellentesque facilisis. Sed arcu est, tempor ac turpis sit amet, ultricies "
+"venenatis augue. Nunc laoreet leo gravida facilisis dapibus. Aliquam convallis ullamcorper felis, sit amet tempor "
+"libero euismod sit amet. Quisque leo augue, finibus et euismod non, venenatis sed libero. Cras pharetra rhoncus "
+"odio, in pharetra lacus porttitor scelerisque. Maecenas eleifend felis vitae diam blandit viverra. Fusce at "
+"ultricies arcu, pharetra finibus enim. Etiam pellentesque semper ligula, sed tincidunt purus. Sed fermentum metus "
+"varius, aliquet libero eget, vehicula erat. Sed ac finibus metus. Pellentesque libero leo, semper et eros nec, "
+"gravida condimentum urna. Cras nec turpis convallis, efficitur lacus at, ultricies ex. Fusce eu neque elementum leo "
+"gravida semper. Duis sed tellus vitae magna fringilla maximus ac ut nisl. Integer id ligula ullamcorper, ultricies "
+"quam sit amet, ullamcorper diam. Maecenas rhoncus nulla eu dui vulputate scelerisque. Vestibulum porttitor eget nibh "
+"a mattis. Mauris tempus at urna blandit dignissim. Proin turpis leo, mattis ut turpis eget, aliquet tempor ante. "
+"Nunc in mollis nunc, et interdum nisi. Cras tristique sollicitudin tortor sit amet ultrices. Proin rhoncus neque "
+"urna. Maecenas bibendum, massa sit amet suscipit suscipit, justo tortor maximus dolor, posuere facilisis nisi tellus "
+"elementum diam. Quisque id eros vel lectus malesuada tincidunt. Donec at orci ac ligula venenatis dignissim sit amet "
+"nec purus. Sed eu neque finibus, tristique ex a, feugiat ante. Pellentesque tincidunt luctus mollis. Nullam blandit "
+"faucibus gravida. Ut sit amet malesuada nibh, vel tincidunt ipsum. Donec suscipit lorem in dui luctus, viverra "
+"imperdiet magna placerat. Pellentesque venenatis eros quis urna efficitur facilisis. Cras ligula magna, tempus "
+"facilisis tincidunt at, varius quis lectus. Sed quam neque, facilisis vel facilisis vel, lobortis ac orci. Nullam "
+"pretium interdum erat ac ultrices. Etiam enim mauris, vehicula nec rhoncus quis, volutpat vel erat. Morbi imperdiet "
+"rhoncus rutrum. Nullam auctor condimentum diam nec faucibus. Etiam sit amet porta nulla, sit amet lobortis enim. "
+"Aenean tincidunt condimentum accumsan. Vestibulum mollis diam risus, vitae ornare enim iaculis non. Nullam vitae "
+"risus tristique, imperdiet augue ut, egestas dolor. Sed sit amet leo eu diam commodo vestibulum id in dolor. Vivamus "
+"tristique molestie faucibus. Duis tempor porttitor turpis ac consectetur. Curabitur condimentum, ipsum eu dignissim "
+"semper, ipsum erat pretium quam, ut maximus erat ligula eu felis. Sed viverra, mauris id tempus tempor, nisi leo "
+"consectetur arcu, ac vulputate lorem mauris non sapien. Maecenas rhoncus magna mauris, in luctus nulla dapibus at. "
+"Sed magna est, ultrices sit amet erat nec, dapibus lacinia massa. Morbi cursus ex in elit auctor egestas. Quisque id "
+"placerat nibh, at mollis tortor. Proin fringilla sodales sapien, ac ullamcorper sem bibendum eget. Donec dui ligula, "
+"viverra eget leo ac, tincidunt fringilla mauris. Quisque vel lectus eget metus feugiat laoreet. Morbi eget "
+"vestibulum enim, ac ultricies lorem. Nam at mollis magna. Etiam vitae orci eu leo facilisis vestibulum. Ut sed "
+"turpis ut nibh iaculis rhoncus. Phasellus sit amet risus pellentesque, gravida eros a, porta nibh. Suspendisse at "
+"tincidunt ligula. Vivamus id libero diam. Morbi viverra ipsum turpis, in ullamcorper enim pellentesque nec. Sed "
+"ultricies, lectus quis pellentesque sodales, arcu diam commodo massa, a vestibulum purus sapien eget risus. Duis "
+"rhoncus in velit in dignissim. Aliquam sit amet metus in quam finibus cursus. Pellentesque eget aliquam justo. Fusce "
+"imperdiet, tellus non venenatis facilisis, diam mi lobortis dolor, at consectetur est massa id elit. Vivamus ante "
+"ex, faucibus et mollis eget, dignissim vel massa. Duis ultricies diam commodo purus facilisis pharetra. Curabitur "
+"pretium massa sed enim vehicula, id vehicula neque vehicula. In quis lectus non mauris pulvinar fermentum. Aliquam "
+"condimentum aliquet dui et congue. Maecenas quis augue eget leo gravida aliquet. Praesent sit amet fermentum odio, "
+"ut placerat nulla. Curabitur sit amet iaculis erat, eu volutpat odio. Ut iaculis ex quis tempus commodo. "
+"Pellentesque cursus eros at velit vulputate, id luctus massa pretium. Morbi ex dui, sodales id finibus id, aliquet a "
+"justo. Maecenas semper leo eget dolor rutrum, at imperdiet nibh eleifend. Aliquam eget purus tortor. Cras rutrum "
+"tortor massa, vel bibendum nunc aliquam vel. Nullam vestibulum, metus vel fermentum elementum, nulla sapien egestas "
+"justo, ac feugiat ex justo nec eros. Donec sit amet nibh mollis, commodo quam sit amet, semper magna. In tortor "
+"magna, elementum nec auctor sed, pellentesque at augue. Sed gravida arcu ac aliquet convallis. Nulla facilisi. Duis "
+"nunc quam, gravida non interdum id, cursus ac leo. Suspendisse vel ipsum nisl. Aliquam at gravida libero. Maecenas "
+"sit amet efficitur orci. Fusce id vehicula sapien. Proin euismod diam non laoreet ultricies. Nunc ullamcorper, nibh "
+"id cursus vehicula, ex purus tempor urna, et euismod orci est sed elit. Duis ut blandit mauris. Ut blandit cursus "
+"eros, sed laoreet nisl efficitur ac. Phasellus dui elit, fringilla sit amet cursus nec, pharetra quis odio. Ut ut "
+"lorem sit amet sem dapibus accumsan. Aenean a laoreet dolor. Donec eu laoreet velit. Etiam id nisi vel nibh dapibus "
+"congue a quis odio. Donec velit risus, semper quis porta non, elementum quis lorem. Interdum et malesuada fames ac "
+"ante ipsum primis in faucibus. Nullam sit amet dolor magna. Maecenas quis sapien sit amet est pulvinar lobortis "
+"efficitur cursus orci. Phasellus tristique mauris lorem, eu ultricies justo ornare condimentum. Integer urna enim, "
+"lobortis id malesuada ut, mattis eget libero. Sed commodo tincidunt eleifend. Fusce sed velit ut dui pellentesque "
+"pellentesque eget vel diam. Aenean nec turpis at tortor consectetur consectetur. Vestibulum ultrices elit at nisl "
+"pellentesque molestie. Maecenas diam dolor, faucibus eget posuere ut, sodales ut eros. Nam vulputate mollis diam nec "
+"gravida. Nam et ullamcorper diam. Aenean non nulla non lorem ullamcorper sagittis non quis erat. Pellentesque "
+"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. "
+"Donec quis mauris ac nibh vestibulum eleifend placerat sed lacus. Suspendisse mi elit, viverra non velit ut, "
+"tincidunt tempus felis. Fusce ullamcorper, arcu nec aliquet porttitor, odio lacus mollis mi, id malesuada tortor "
+"velit aliquet turpis. Sed hendrerit felis nec faucibus ornare. Nulla ut metus eget augue malesuada posuere eget eu "
+"tortor. Cras ultrices odio sit amet porttitor vehicula. Sed vulputate leo vitae justo viverra, nec volutpat eros "
+"consectetur. Nunc nunc tellus, porta in arcu in, vulputate ultricies tellus. Fusce commodo efficitur lorem, sit amet "
+"lacinia sapien sollicitudin at. Etiam aliquet non mi vitae ornare. Cras condimentum imperdiet elit eu dictum. Donec "
+"sed enim sed massa tempor porta et sit amet felis. Nam interdum ornare sem, in tincidunt risus consectetur vel. Ut "
+"convallis purus mauris, in consequat ligula ullamcorper ut. Quisque elit ipsum, accumsan eget ligula vitae, "
+"sollicitudin luctus tellus. Nunc pretium turpis ligula, id dignissim lorem suscipit eu. Nulla facilisi. Sed lectus "
+"odio, vehicula vel vulputate id, ultrices non ipsum. Donec arcu quam, consequat eget aliquet sit amet, ullamcorper "
+"non nibh. Etiam finibus, mi id lobortis sagittis, leo leo lobortis lectus, sit amet aliquam dui odio sit amet massa. "
+"Suspendisse iaculis urna ac lectus gravida, iaculis efficitur tellus hendrerit. Sed tellus enim, condimentum in "
+"augue eget, sagittis ullamcorper sem. Suspendisse vitae aliquet libero. Aenean quis purus in sapien dapibus "
+"suscipit. Sed commodo nunc in lacus bibendum, vel tincidunt ante ornare. Ut tristique luctus volutpat. Class aptent "
+"taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque a ultricies orci, eu porta "
+"odio. Vivamus sapien arcu, ultrices vel dui ut, luctus viverra purus. Praesent fringilla sed odio quis pretium. "
+"Vestibulum ullamcorper nisi tortor, id sollicitudin lectus tempor a. Ut malesuada sapien eu sapien posuere, non "
+"euismod eros porta. Nunc vel tincidunt ligula. Cras dolor ante, tristique tempor metus quis, mollis vulputate orci. "
+"Curabitur vitae nisl euismod, elementum purus vel, dictum lorem. Nunc eu mauris at metus porttitor dignissim ut eu "
+"neque. In tempor rhoncus neque sit amet commodo. Maecenas sed lacus semper, tempus enim ac, fermentum lorem. Nullam "
+"sollicitudin convallis turpis. Curabitur finibus placerat viverra. Pellentesque convallis condimentum tortor id "
+"efficitur. Proin semper pretium est, et vehicula ex cursus a. Nam ut felis purus. Phasellus eget felis eget leo "
+"dapibus vestibulum. Nulla eleifend malesuada turpis, quis faucibus eros. Nam aliquet euismod viverra. Ut quis semper "
+"felis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque at nulla "
+"arcu. Integer ut tellus ac sapien maximus tincidunt sed vitae risus. Nulla viverra, nibh eget eleifend aliquam, quam "
+"quam tempor massa, eu semper ipsum lacus in turpis. Nulla sed purus enim. Nullam sed fermentum ipsum. Sed dui nisi, "
+"elementum a auctor at, ultrices et nibh. Phasellus aliquam nulla ut lacinia accumsan. Phasellus sed arcu ligula. "
+"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam fermentum magna vitae dui sagittis tempor. Vivamus "
+"eu ligula blandit, imperdiet arcu at, rutrum sem. Aliquam erat volutpat. Quisque luctus enim quis volutpat lobortis. "
+"Vestibulum eget sodales libero. Aenean at condimentum est. Proin eget massa vel nulla efficitur tempor eget at enim. "
+"Integer enim sapien, ornare luctus nisl non, pretium facilisis ex. Donec pretium ligula ligula, a facilisis turpis "
+"hendrerit at. Nullam eget malesuada justo, at molestie quam. Sed consequat massa eu faucibus maximus. Curabitur "
+"placerat orci sapien, sit amet semper magna sodales non. Ut fermentum accumsan odio in consectetur. Morbi neque mi, "
+"vulputate nec mi ut, cursus scelerisque lectus. Nulla sapien enim, finibus id ipsum luctus, consequat ullamcorper "
+"lectus. Sed volutpat sed massa in sodales. Morbi lacinia diam eu commodo vulputate. Fusce aliquet pulvinar dolor in "
+"egestas. Fusce molestie commodo leo eu ultricies. Nulla mollis rhoncus pharetra. Pellentesque rutrum mauris ac lorem "
+"posuere, a eleifend mi rutrum. Nulla porta turpis aliquet felis congue rutrum. Fusce quis arcu in sem placerat "
+"condimentum a ut turpis. Quisque quis porttitor nulla. Donec sit amet quam tincidunt, pulvinar erat id, molestie "
+"dolor. Praesent luctus vitae nunc vitae pellentesque. Praesent faucibus sed urna ut lacinia. Vivamus id justo quis "
+"dolor porta rutrum nec nec odio. Cras euismod tortor quis diam ultrices, eu mattis nisi consectetur. Fusce mattis "
+"nisi vel condimentum molestie. Fusce fringilla ut nibh volutpat elementum. Mauris posuere consectetur leo a aliquet. "
+"Donec quis sodales sapien. Maecenas ut felis tempus, eleifend mauris et, faucibus mi. Quisque fringilla orci arcu, "
+"sit amet porta risus hendrerit non. Aenean id sem nisi. Nullam non nisl vestibulum, pellentesque nisl et, imperdiet "
+"ligula. Sed laoreet fringilla felis. Proin ac dolor viverra tellus mollis aliquet eget et neque. Suspendisse mattis "
+"nulla vitae nulla sagittis blandit. Sed at tortor rutrum, ornare magna nec, pellentesque nisi. Etiam non aliquet "
+"tellus. Aliquam at ex suscipit, posuere sem sit amet, tincidunt.";
+
+#endif /* __BLENDER_TESTING_BLI_RESSOURCE_STRING_H__ */
diff --git a/tests/gtests/blenlib/BLI_stack_test.cc b/tests/gtests/blenlib/BLI_stack_test.cc
index c4884cb8940..44956a589dc 100644
--- a/tests/gtests/blenlib/BLI_stack_test.cc
+++ b/tests/gtests/blenlib/BLI_stack_test.cc
@@ -11,6 +11,14 @@ extern "C" {
#define SIZE 1024
+/* number of items per chunk. use a small value to expose bugs */
+#define STACK_CHUNK_SIZE 8
+
+/* Ensure block size is set to #STACK_NEW_EX_ARGS */
+#define BLI_stack_new(esize, descr) \
+ BLI_stack_new_ex(esize, descr, esize * STACK_CHUNK_SIZE)
+
+
TEST(stack, Empty)
{
BLI_Stack *stack;
@@ -88,17 +96,82 @@ TEST(stack, String)
BLI_stack_free(stack);
}
+TEST(stack, Peek)
+{
+ const int tot = SIZE;
+ int i;
+
+ BLI_Stack *stack;
+ const short in[] = {1, 10, 100, 1000};
+
+ stack = BLI_stack_new(sizeof(*in), __func__);
+
+ for (i = 0; i < tot; i++) {
+ BLI_stack_push(stack, &in[i % ARRAY_SIZE(in)]);
+ }
+
+ for (i = tot - 1; i >= 0; i--, BLI_stack_discard(stack)) {
+ short *ret = (short *)BLI_stack_peek(stack);
+ EXPECT_EQ(*ret, in[i % ARRAY_SIZE(in)]);
+ }
+
+ EXPECT_EQ(BLI_stack_is_empty(stack), true);
+}
+
+/* Check that clearing the stack leaves in it a correct state. */
+TEST(stack, Clear)
+{
+ const int tot_rerun = 4;
+ int rerun;
+
+ /* based on range test */
+ int tot = SIZE;
+ BLI_Stack *stack;
+ int in, out;
+
+ /* use a small chunk size to ensure we test */
+ stack = BLI_stack_new(sizeof(in), __func__);
+
+ for (rerun = 0; rerun < tot_rerun; rerun++) {
+ for (in = 0; in < tot; in++) {
+ BLI_stack_push(stack, (void *)&in);
+ }
+
+ BLI_stack_clear(stack);
+ EXPECT_EQ(BLI_stack_is_empty(stack), true);
+
+ /* and again, this time check its valid */
+ for (in = 0; in < tot; in++) {
+ BLI_stack_push(stack, (void *)&in);
+ }
+
+ for (in = tot - 1; in >= 0; in--) {
+ EXPECT_EQ(BLI_stack_is_empty(stack), false);
+ BLI_stack_pop(stack, (void *)&out);
+ EXPECT_EQ(in, out);
+ }
+
+ EXPECT_EQ(BLI_stack_is_empty(stack), true);
+
+ /* without this, we wont test case when mixed free/used */
+ tot /= 2;
+ }
+
+ BLI_stack_free(stack);
+}
+
+
TEST(stack, Reuse)
{
const int sizes[] = {3, 11, 81, 400, 999, 12, 1, 9721, 7, 99, 5, 0};
int sizes_test[ARRAY_SIZE(sizes)];
const int *s;
- int in, out, i;
+ int out, i;
int sum, sum_test;
BLI_Stack *stack;
- stack = BLI_stack_new(sizeof(in), __func__);
+ stack = BLI_stack_new(sizeof(i), __func__);
/* add a bunch of numbers, ensure we get same sum out */
sum = 0;
diff --git a/tests/gtests/blenlib/BLI_string_test.cc b/tests/gtests/blenlib/BLI_string_test.cc
index 4c5c410dcb2..fa10e21730b 100644
--- a/tests/gtests/blenlib/BLI_string_test.cc
+++ b/tests/gtests/blenlib/BLI_string_test.cc
@@ -36,7 +36,7 @@ int mk_wcswidth(const wchar_t *pwcs, size_t n)
TEST(string, StrPartition)
{
const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
- char *sep, *suf;
+ const char *sep, *suf;
size_t pre_ln;
{
@@ -95,7 +95,7 @@ TEST(string, StrPartition)
TEST(string, StrRPartition)
{
const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
- char *sep, *suf;
+ const char *sep, *suf;
size_t pre_ln;
{
@@ -150,11 +150,42 @@ TEST(string, StrRPartition)
}
}
+/* BLI_str_partition_ex */
+TEST(string, StrPartitionEx)
+{
+ const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
+ const char *sep, *suf;
+ size_t pre_ln;
+
+ /* Only considering 'from_right' cases here. */
+
+ {
+ const char *str = "mat.e-r_ia.l";
+
+ /* "mat.e-r_ia.l" over "mat.e-r" -> "mat.e", '.', "r_ia.l", 3 */
+ pre_ln = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true);
+ EXPECT_EQ(5, pre_ln);
+ EXPECT_EQ(&str[5], sep);
+ EXPECT_STREQ("r_ia.l", suf);
+ }
+
+ /* Corner cases. */
+ {
+ const char *str = "mate.rial";
+
+ /* "mate.rial" over "mate" -> "mate.rial", NULL, NULL, 4 */
+ pre_ln = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true);
+ EXPECT_EQ(4, pre_ln);
+ EXPECT_EQ(NULL, sep);
+ EXPECT_EQ(NULL, suf);
+ }
+}
+
/* BLI_str_partition_utf8 */
TEST(string, StrPartitionUtf8)
{
const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
- char *sep, *suf;
+ const char *sep, *suf;
size_t pre_ln;
{
@@ -213,7 +244,7 @@ TEST(string, StrPartitionUtf8)
TEST(string, StrRPartitionUtf8)
{
const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
- char *sep, *suf;
+ const char *sep, *suf;
size_t pre_ln;
{
@@ -268,6 +299,37 @@ TEST(string, StrRPartitionUtf8)
}
}
+/* BLI_str_partition_ex_utf8 */
+TEST(string, StrPartitionExUtf8)
+{
+ const unsigned int delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
+ const char *sep, *suf;
+ size_t pre_ln;
+
+ /* Only considering 'from_right' cases here. */
+
+ {
+ const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial";
+
+ /* "ma\xc3\xb1te-r\xe2\x98\xafial" over "ma\xc3\xb1te" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
+ pre_ln = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true);
+ EXPECT_EQ(2, pre_ln);
+ EXPECT_EQ(&str[2], sep);
+ EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
+ }
+
+ /* Corner cases. */
+ {
+ const char *str = "mate\xe2\x98\xafrial";
+
+ /* "mate\xe2\x98\xafrial" over "mate" -> "mate\xe2\x98\xafrial", NULL, NULL, 4 */
+ pre_ln = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true);
+ EXPECT_EQ(4, pre_ln);
+ EXPECT_EQ(NULL, sep);
+ EXPECT_EQ(NULL, suf);
+ }
+}
+
/* BLI_str_format_int_grouped */
TEST(string, StrFormatIntGrouped)
{
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index 07b89a9042e..acd9f944e4c 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -38,6 +38,12 @@ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LIN
BLENDER_TEST(BLI_stack "bf_blenlib")
BLENDER_TEST(BLI_math_color "bf_blenlib")
BLENDER_TEST(BLI_math_geom "bf_blenlib")
+BLENDER_TEST(BLI_math_base "bf_blenlib")
BLENDER_TEST(BLI_string "bf_blenlib")
BLENDER_TEST(BLI_path_util "bf_blenlib;extern_wcwidth;${ZLIB_LIBRARIES}")
+BLENDER_TEST(BLI_polyfill2d "bf_blenlib")
BLENDER_TEST(BLI_listbase "bf_blenlib")
+BLENDER_TEST(BLI_hash_mm2a "bf_blenlib")
+BLENDER_TEST(BLI_ghash "bf_blenlib")
+
+BLENDER_TEST_PERFORMANCE(BLI_ghash_performance "bf_blenlib")
diff --git a/tests/gtests/testing/testing_main.cc b/tests/gtests/testing/testing_main.cc
index ef8e743b642..b2dcc445aca 100644
--- a/tests/gtests/testing/testing_main.cc
+++ b/tests/gtests/testing/testing_main.cc
@@ -28,7 +28,7 @@
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
- google::ParseCommandLineFlags(&argc, &argv, true);
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
return RUN_ALL_TESTS();
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index 85c68693792..fd2176e64d7 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -48,6 +48,7 @@ else()
endif()
# for testing with valgrind prefix: valgrind --track-origins=yes --error-limit=no
+set(TEST_BLENDER_EXE_BARE ${TEST_BLENDER_EXE})
set(TEST_BLENDER_EXE ${TEST_BLENDER_EXE} --background -noaudio --factory-startup --env-system-scripts ${CMAKE_SOURCE_DIR}/release/scripts)
@@ -72,6 +73,16 @@ if(USE_EXPERIMENTAL_TESTS)
)
endif()
+# ------------------------------------------------------------------------------
+# PY API TESTS
+add_test(script_pyapi_bpy_path ${TEST_BLENDER_EXE}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_bpy_path.py
+)
+
+add_test(script_pyapi_bpy_utils_units ${TEST_BLENDER_EXE}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_bpy_utils_units.py
+)
+
# test running mathutils testing script
add_test(script_pyapi_mathutils ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_mathutils.py
@@ -88,6 +99,8 @@ add_test(bevel ${TEST_BLENDER_EXE}
# IO TESTS
# OBJ Import tests
+# disabled until updated & working
+if(FALSE)
add_test(import_obj_cube ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.obj\(filepath='${TEST_SRC_DIR}/io_tests/obj/cube.obj'\)
@@ -108,6 +121,7 @@ add_test(import_obj_makehuman ${TEST_BLENDER_EXE}
--md5=c9f78b185e58358daa4ecaecfa75464e --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_obj_makehuman.blend
)
+endif()
# OBJ Export tests
add_test(export_obj_cube ${TEST_BLENDER_EXE}
@@ -116,7 +130,7 @@ add_test(export_obj_cube ${TEST_BLENDER_EXE}
--run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_cube.obj',use_selection=False\)
--md5_source=${TEST_OUT_DIR}/export_obj_cube.obj
--md5_source=${TEST_OUT_DIR}/export_obj_cube.mtl
- --md5=70bdc394c2726203ad26c085176e3484 --md5_method=FILE
+ --md5=e776c6f8e9e0afba346e85bcd10b8e99 --md5_method=FILE
)
add_test(export_obj_nurbs ${TEST_BLENDER_EXE}
@@ -128,6 +142,8 @@ add_test(export_obj_nurbs ${TEST_BLENDER_EXE}
--md5=a733ae4fa4a591ea9b0912da3af042de --md5_method=FILE
)
+# disabled until updated & working
+if(FALSE)
add_test(export_obj_all_objects ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_scene/all_objects.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -136,6 +152,7 @@ add_test(export_obj_all_objects ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_obj_all_objects.mtl
--md5=04b3ed97cede07a19548fc518ce9f8ca --md5_method=FILE
)
+endif()
@@ -162,6 +179,8 @@ add_test(import_ply_small_holes ${TEST_BLENDER_EXE}
)
# PLY Export
+# disabled until updated & working
+if(FALSE)
add_test(export_ply_cube_all_data ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_geometry/cube_all_data.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -177,6 +196,7 @@ add_test(export_ply_suzanne_all_data ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_ply_suzanne_all_data.ply
--md5=68ba23f02efd6511bfd093f45f703221 --md5_method=FILE
)
+endif()
add_test(export_ply_vertices ${TEST_BLENDER_EXE} # lame, add a better one
${TEST_SRC_DIR}/io_tests/blend_geometry/vertices.blend
@@ -188,6 +208,8 @@ add_test(export_ply_vertices ${TEST_BLENDER_EXE} # lame, add a better one
# STL Import tests
+# disabled until updated & working
+if(FALSE)
add_test(import_stl_cube ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_mesh.stl\(filepath='${TEST_SRC_DIR}/io_tests/stl/cube.stl'\)
@@ -208,8 +230,11 @@ add_test(import_stl_knot_max_simplified ${TEST_BLENDER_EXE}
--md5=baf82803f45a84ec4ddbad9cef57dd3e --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_stl_knot_max_simplified.blend
)
+endif()
# STL Export
+# disabled until updated & working
+if(FALSE)
add_test(export_stl_cube_all_data ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_geometry/cube_all_data.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -233,9 +258,12 @@ add_test(export_stl_vertices ${TEST_BLENDER_EXE} # lame, add a better one
--md5_source=${TEST_OUT_DIR}/export_stl_vertices.stl
--md5=3fd3c877e573beeebc782532cc005820 --md5_method=FILE
)
+endif()
# X3D Import
+# disabled until updated & working
+if(FALSE)
add_test(import_x3d_cube ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.x3d\(filepath='${TEST_SRC_DIR}/io_tests/x3d/color_cube.x3d'\)
@@ -281,10 +309,13 @@ add_test(export_x3d_all_objects ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_x3d_all_objects.x3d
--md5=f5f9fa4c5619a0eeab66685aafd2f7f0 --md5_method=FILE
)
+endif()
# 3DS Import
+# disabled until updated & working
+if(FALSE)
add_test(import_3ds_cube ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
--run={'FINISHED'}&bpy.ops.import_scene.autodesk_3ds\(filepath='${TEST_SRC_DIR}/io_tests/3ds/cube.3ds'\)
@@ -305,8 +336,11 @@ add_test(import_3ds_hierarchy_greek_trireme ${TEST_BLENDER_EXE}
--md5=b62ee30101e8999cb91ef4f8a8760056 --md5_method=SCENE
--write-blend=${TEST_OUT_DIR}/import_3ds_hierarchy_greek_trireme.blend
)
+endif()
# 3DS Export
+# disabled until updated & working
+if(FALSE)
add_test(export_3ds_cube ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -330,11 +364,14 @@ add_test(export_3ds_all_objects ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_3ds_all_objects.3ds
--md5=68447761ab0ca38e1e22e7c177ed48a8 --md5_method=FILE
)
+endif()
# FBX Export
# 'use_metadata=False' for reliable md5's
+# disabled until updated & working
+if(FALSE)
add_test(export_fbx_cube ${TEST_BLENDER_EXE}
${TEST_SRC_DIR}/io_tests/blend_geometry/all_quads.blend
--python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py --
@@ -358,3 +395,29 @@ add_test(export_fbx_all_objects ${TEST_BLENDER_EXE}
--md5_source=${TEST_OUT_DIR}/export_fbx_all_objects.fbx
--md5=b35eb2a9d0e73762ecae2278c25a38ac --md5_method=FILE
)
+endif()
+
+if(WITH_CYCLES)
+ if(OPENIMAGEIO_IDIFF AND EXISTS "${TEST_SRC_DIR}/cycles/ctests/shader")
+ add_test(cycles_reports_test
+ ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py
+ -blender "${TEST_BLENDER_EXE_BARE}"
+ -testdir "${TEST_SRC_DIR}/cycles/ctests/reports"
+ -idiff "${OPENIMAGEIO_IDIFF}"
+ )
+ add_test(cycles_render_test
+ ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py
+ -blender "${TEST_BLENDER_EXE_BARE}"
+ -testdir "${TEST_SRC_DIR}/cycles/ctests/render"
+ -idiff "${OPENIMAGEIO_IDIFF}"
+ )
+ add_test(cycles_shaders_test
+ ${CMAKE_CURRENT_LIST_DIR}/cycles_render_tests.py
+ -blender "${TEST_BLENDER_EXE_BARE}"
+ -testdir "${TEST_SRC_DIR}/cycles/ctests/shader"
+ -idiff "${OPENIMAGEIO_IDIFF}"
+ )
+ else()
+ MESSAGE(STATUS "Disabling Cycles tests because tests folder does not exist")
+ endif()
+endif()
diff --git a/tests/python/batch_import.py b/tests/python/batch_import.py
index dea08b45c3a..8fc679a7c15 100644
--- a/tests/python/batch_import.py
+++ b/tests/python/batch_import.py
@@ -78,7 +78,9 @@ def batch_import(operator="",
path = os.path.abspath(path)
match_upper = match.upper()
- pattern_match = lambda a: fnmatch.fnmatchcase(a.upper(), match_upper)
+
+ def pattern_match(a):
+ return fnmatch.fnmatchcase(a.upper(), match_upper)
def file_generator(path):
for dirpath, dirnames, filenames in os.walk(path):
diff --git a/tests/python/bl_load_addons.py b/tests/python/bl_load_addons.py
index f04ae64ee73..29304400005 100644
--- a/tests/python/bl_load_addons.py
+++ b/tests/python/bl_load_addons.py
@@ -20,24 +20,57 @@
# simple script to enable all addons, and disable
+"""
+./blender.bin --background -noaudio --factory-startup --python tests/python/bl_load_addons.py
+"""
+
import bpy
import addon_utils
+import os
import sys
import imp
+BLACKLIST_DIRS = (
+ os.path.join(bpy.utils.resource_path('USER'), "scripts"),
+ ) + tuple(addon_utils.paths()[1:])
+BLACKLIST_ADDONS = set()
+
+
+def _init_addon_blacklist():
+
+ # in case we built without cycles
+ if not bpy.app.build_options.cycles:
+ BLACKLIST_ADDONS.add("cycles")
+
+ # in case we built without freestyle
+ if not bpy.app.build_options.freestyle:
+ BLACKLIST_ADDONS.add("render_freestyle_svg")
+
+ # netrender has known problems re-registering
+ BLACKLIST_ADDONS.add("netrender")
+
+
+def addon_modules_sorted():
+ modules = addon_utils.modules({})
+ modules[:] = [
+ mod for mod in modules
+ if not (mod.__file__.startswith(BLACKLIST_DIRS))
+ if not (mod.__name__ in BLACKLIST_ADDONS)]
+ modules.sort(key=lambda mod: mod.__name__)
+ return modules
+
def disable_addons():
# first disable all
addons = bpy.context.user_preferences.addons
for mod_name in list(addons.keys()):
- addon_utils.disable(mod_name)
+ addon_utils.disable(mod_name, default_set=True)
assert(bool(addons) is False)
def test_load_addons():
- modules = addon_utils.modules({})
- modules.sort(key=lambda mod: mod.__name__)
+ modules = addon_modules_sorted()
disable_addons()
@@ -48,8 +81,8 @@ def test_load_addons():
for mod in modules:
mod_name = mod.__name__
print("\tenabling:", mod_name)
- addon_utils.enable(mod_name)
- if mod_name not in addons:
+ addon_utils.enable(mod_name, default_set=True)
+ if (mod_name not in addons) and (mod_name not in BLACKLIST_ADDONS):
addons_fail.append(mod_name)
if addons_fail:
@@ -62,8 +95,7 @@ def test_load_addons():
def reload_addons(do_reload=True, do_reverse=True):
- modules = addon_utils.modules({})
- modules.sort(key=lambda mod: mod.__name__)
+ modules = addon_modules_sorted()
addons = bpy.context.user_preferences.addons
disable_addons()
@@ -73,25 +105,28 @@ def reload_addons(do_reload=True, do_reverse=True):
for mod in modules:
mod_name = mod.__name__
print("\tenabling:", mod_name)
- addon_utils.enable(mod_name)
+ addon_utils.enable(mod_name, default_set=True)
assert(mod_name in addons)
- for mod in addon_utils.modules({}):
+ for mod in modules:
mod_name = mod.__name__
print("\tdisabling:", mod_name)
- addon_utils.disable(mod_name)
+ addon_utils.disable(mod_name, default_set=True)
assert(not (mod_name in addons))
# now test reloading
if do_reload:
imp.reload(sys.modules[mod_name])
- if do_reverse:
- # in case order matters when it shouldn't
- modules.reverse()
+ if do_reverse:
+ # in case order matters when it shouldn't
+ modules.reverse()
def main():
+
+ _init_addon_blacklist()
+
# first load addons, print a list of all addons that fail
test_load_addons()
diff --git a/tests/python/bl_load_py_modules.py b/tests/python/bl_load_py_modules.py
index 9677397e01d..4256cba0933 100644
--- a/tests/python/bl_load_py_modules.py
+++ b/tests/python/bl_load_py_modules.py
@@ -20,6 +20,10 @@
# simple script to enable all addons, and disable
+"""
+./blender.bin --background -noaudio --factory-startup --python tests/python/bl_load_py_modules.py
+"""
+
import bpy
import addon_utils
@@ -28,10 +32,26 @@ import os
BLACKLIST = {
"bl_i18n_utils",
+ "bl_previews_utils",
"cycles",
"io_export_dxf", # TODO, check on why this fails
+ 'io_import_dxf', # Because of cydxfentity.so dependency
}
+if not bpy.app.build_options.freestyle:
+ BLACKLIST.add("render_freestyle_svg")
+
+BLACKLIST_DIRS = (
+ os.path.join(bpy.utils.resource_path('USER'), "scripts"),
+ ) + tuple(addon_utils.paths()[1:])
+
+
+def addon_modules_sorted():
+ modules = addon_utils.modules({})
+ modules[:] = [mod for mod in modules if not mod.__file__.startswith(BLACKLIST_DIRS)]
+ modules.sort(key=lambda mod: mod.__name__)
+ return modules
+
def source_list(path, filename_check=None):
from os.path import join
@@ -47,20 +67,22 @@ def source_list(path, filename_check=None):
def load_addons():
- modules = addon_utils.modules({})
- modules.sort(key=lambda mod: mod.__name__)
+ modules = addon_modules_sorted()
addons = bpy.context.user_preferences.addons
# first disable all
for mod_name in list(addons.keys()):
- addon_utils.disable(mod_name)
+ addon_utils.disable(mod_name, default_set=True)
assert(bool(addons) is False)
for mod in modules:
mod_name = mod.__name__
- addon_utils.enable(mod_name)
- assert(mod_name in addons)
+ if mod_name in BLACKLIST:
+ continue
+ addon_utils.enable(mod_name, default_set=True)
+ if not (mod_name in addons):
+ raise Exception("'addon_utils.enable(%r)' call failed" % mod_name)
def load_modules():
@@ -79,9 +101,10 @@ def load_modules():
for script_path in paths:
for mod_dir in sys.path:
if mod_dir.startswith(script_path):
- if mod_dir not in module_paths:
- if os.path.exists(mod_dir):
- module_paths.append(mod_dir)
+ if not mod_dir.startswith(BLACKLIST_DIRS):
+ if mod_dir not in module_paths:
+ if os.path.exists(mod_dir):
+ module_paths.append(mod_dir)
#
# collect modules from our paths.
@@ -140,7 +163,8 @@ def load_modules():
ignore_paths = [
os.sep + "presets" + os.sep,
os.sep + "templates" + os.sep,
- ] + [(os.sep + f + os.sep) for f in BLACKLIST]
+ ] + ([(os.sep + f + os.sep) for f in BLACKLIST] +
+ [(os.sep + f + ".py") for f in BLACKLIST])
for f in source_files:
ok = False
diff --git a/tests/python/bl_mesh_modifiers.py b/tests/python/bl_mesh_modifiers.py
index 2db38895f9b..0121be29dd6 100644
--- a/tests/python/bl_mesh_modifiers.py
+++ b/tests/python/bl_mesh_modifiers.py
@@ -197,8 +197,9 @@ def defaults_object(obj):
obj.show_wire = True
if obj.type == 'MESH':
+ obj.show_all_edges = True
+
mesh = obj.data
- mesh.show_all_edges = True
mesh.show_normal_vertex = True
diff --git a/tests/python/bl_pyapi_bpy_path.py b/tests/python/bl_pyapi_bpy_path.py
new file mode 100644
index 00000000000..2d6019fbb07
--- /dev/null
+++ b/tests/python/bl_pyapi_bpy_path.py
@@ -0,0 +1,41 @@
+# Apache License, Version 2.0
+
+# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_bpy_path.py -- --verbose
+import unittest
+
+
+class TestBpyPath(unittest.TestCase):
+ def test_ensure_ext(self):
+ from bpy.path import ensure_ext
+
+ # Should work with both strings and bytes.
+ self.assertEqual(ensure_ext('demo', '.blend'), 'demo.blend')
+ self.assertEqual(ensure_ext(b'demo', b'.blend'), b'demo.blend')
+
+ # Test different cases.
+ self.assertEqual(ensure_ext('demo.blend', '.blend'), 'demo.blend')
+ self.assertEqual(ensure_ext('demo.BLEND', '.blend'), 'demo.BLEND')
+ self.assertEqual(ensure_ext('demo.blend', '.BLEND'), 'demo.blend')
+
+ # Test empty extensions, compound extensions etc.
+ self.assertEqual(ensure_ext('demo', 'blend'), 'demoblend')
+ self.assertEqual(ensure_ext('demo', ''), 'demo')
+ self.assertEqual(ensure_ext('demo', '.json.gz'), 'demo.json.gz')
+ self.assertEqual(ensure_ext('demo.json.gz', '.json.gz'), 'demo.json.gz')
+ self.assertEqual(ensure_ext('demo.json', '.json.gz'), 'demo.json.json.gz')
+ self.assertEqual(ensure_ext('', ''), '')
+ self.assertEqual(ensure_ext('', '.blend'), '.blend')
+
+ # Test case-sensitive behaviour.
+ self.assertEqual(ensure_ext('demo', '.blend', True), 'demo.blend')
+ self.assertEqual(ensure_ext('demo.BLEND', '.blend', True), 'demo.BLEND.blend')
+ self.assertEqual(ensure_ext('demo', 'Blend', True), 'demoBlend')
+ self.assertEqual(ensure_ext('demoBlend', 'blend', True), 'demoBlendblend')
+ self.assertEqual(ensure_ext('demo', '', True), 'demo')
+
+
+if __name__ == '__main__':
+ import sys
+
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [])
+ unittest.main()
diff --git a/tests/python/bl_pyapi_units.py b/tests/python/bl_pyapi_bpy_utils_units.py
index 128cc100b25..f40dab4b5eb 100644
--- a/tests/python/bl_pyapi_units.py
+++ b/tests/python/bl_pyapi_bpy_utils_units.py
@@ -1,6 +1,6 @@
# Apache License, Version 2.0
-# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_units.py -- --verbose
+# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_bpy_utils_units.py -- --verbose
import unittest
from bpy.utils import units
diff --git a/tests/python/bl_pyapi_mathutils.py b/tests/python/bl_pyapi_mathutils.py
index 85232e465d7..b7f61df0e40 100644
--- a/tests/python/bl_pyapi_mathutils.py
+++ b/tests/python/bl_pyapi_mathutils.py
@@ -2,7 +2,7 @@
# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_mathutils.py -- --verbose
import unittest
-from mathutils import Matrix, Vector
+from mathutils import Matrix, Vector, Quaternion
from mathutils import kdtree
import math
@@ -210,6 +210,35 @@ class VectorTesting(unittest.TestCase):
self.assertAlmostEqual(v.angle(v.orthogonal()), angle_90d)
+class QuaternionTesting(unittest.TestCase):
+
+ def test_to_expmap(self):
+ q = Quaternion((0, 0, 1), math.radians(90))
+
+ e = q.to_exponential_map()
+ self.assertAlmostEqual(e.x, 0)
+ self.assertAlmostEqual(e.y, 0)
+ self.assertAlmostEqual(e.z, math.radians(90), 6)
+
+ def test_expmap_axis_normalization(self):
+ q = Quaternion((1, 1, 0), 2)
+ e = q.to_exponential_map()
+
+ self.assertAlmostEqual(e.x, 2 * math.sqrt(0.5), 6)
+ self.assertAlmostEqual(e.y, 2 * math.sqrt(0.5), 6)
+ self.assertAlmostEqual(e.z, 0)
+
+ def test_from_expmap(self):
+ e = Vector((1, 1, 0))
+ q = Quaternion(e)
+ axis, angle = q.to_axis_angle()
+
+ self.assertAlmostEqual(angle, math.sqrt(2), 6)
+ self.assertAlmostEqual(axis.x, math.sqrt(0.5), 6)
+ self.assertAlmostEqual(axis.y, math.sqrt(0.5), 6)
+ self.assertAlmostEqual(axis.z, 0)
+
+
class KDTreeTesting(unittest.TestCase):
@staticmethod
diff --git a/tests/python/bl_rna_defaults.py b/tests/python/bl_rna_defaults.py
new file mode 100644
index 00000000000..1d6f82b06c2
--- /dev/null
+++ b/tests/python/bl_rna_defaults.py
@@ -0,0 +1,117 @@
+# Apache License, Version 2.0
+
+# ./blender.bin --background -noaudio --factory-startup --python tests/python/bl_rna_defaults.py
+
+import bpy
+
+DUMMY_NAME = "Untitled"
+DUMMY_PATH = __file__
+GLOBALS = {
+ "error_num": 0,
+ }
+
+
+def validate_defaults(test_id, o):
+
+ def warning(prop_id, val_real, val_default):
+ print("Error %s: '%s.%s' is:%r, expected:%r" %
+ (test_id, o.__class__.__name__, prop_id, val_real, val_default))
+ GLOBALS["error_num"] += 1
+
+ properties = type(o).bl_rna.properties.items()
+ for prop_id, prop in properties:
+ if prop_id == "rna_type":
+ continue
+ prop_type = prop.type
+ if prop_type in {'STRING', 'COLLECTION'}:
+ continue
+
+ if prop_type == 'POINTER':
+ # traverse down pointers if they're set
+ val_real = getattr(o, prop_id)
+ if (val_real is not None) and (not isinstance(val_real, bpy.types.ID)):
+ validate_defaults("%s.%s" % (test_id, prop_id), val_real)
+ elif prop_type in {'INT', 'BOOL'}:
+ array_length = prop.array_length
+ if array_length == 0:
+ val_real = getattr(o, prop_id)
+ val_default = prop.default
+ if val_real != val_default:
+ warning(prop_id, val_real, val_default)
+ else:
+ pass # TODO, array defaults
+ elif prop_type == 'FLOAT':
+ array_length = prop.array_length
+ if array_length == 0:
+ val_real = getattr(o, prop_id)
+ val_default = prop.default
+ if val_real != val_default:
+ warning(prop_id, val_real, val_default)
+ else:
+ pass # TODO, array defaults
+ elif prop_type == 'ENUM':
+ val_real = getattr(o, prop_id)
+ if prop.is_enum_flag:
+ val_default = prop.default_flag
+ else:
+ val_default = prop.default
+ if val_real != val_default:
+ warning(prop_id, val_real, val_default)
+
+ # print(prop_id, prop_type)
+
+
+def _test_id_gen(data_attr, args_create=(DUMMY_NAME,), create_method="new"):
+ def test_gen(test_id):
+ id_collection = getattr(bpy.data, data_attr)
+ create_fn = getattr(id_collection, create_method)
+ o = create_fn(*args_create)
+ o.user_clear()
+ validate_defaults(test_id, o)
+ id_collection.remove(o)
+ return test_gen
+
+
+test_Action = _test_id_gen("actions")
+test_Armature = _test_id_gen("armatures")
+test_Camera = _test_id_gen("cameras")
+test_Group = _test_id_gen("groups")
+test_Lattice = _test_id_gen("lattices")
+test_LineStyle = _test_id_gen("linestyles")
+test_Mask = _test_id_gen("masks")
+test_Material = _test_id_gen("materials")
+test_Mesh = _test_id_gen("meshes")
+test_MetaBall = _test_id_gen("metaballs")
+test_MovieClip = _test_id_gen("movieclips", args_create=(DUMMY_PATH,), create_method="load")
+test_Object = _test_id_gen("objects", args_create=(DUMMY_NAME, None))
+test_Palette = _test_id_gen("palettes")
+test_Particle = _test_id_gen("particles")
+test_Scene = _test_id_gen("scenes")
+test_Sound = _test_id_gen("sounds", args_create=(DUMMY_PATH,), create_method="load")
+test_Speaker = _test_id_gen("speakers")
+test_Text = _test_id_gen("texts")
+test_VectorFont = _test_id_gen("fonts", args_create=("<builtin>",), create_method="load")
+test_World = _test_id_gen("worlds")
+
+ns = globals()
+for t in bpy.data.curves.bl_rna.functions["new"].parameters["type"].enum_items.keys():
+ ns["test_Curve_%s" % t] = _test_id_gen("curves", args_create=(DUMMY_NAME, t))
+for t in bpy.data.lamps.bl_rna.functions["new"].parameters["type"].enum_items.keys():
+ ns["test_Lamp_%s" % t] = _test_id_gen("lamps", args_create=(DUMMY_NAME, t))
+# types are a dynamic enum, have to hard-code.
+for t in "ShaderNodeTree", "CompositorNodeTree", "TextureNodeTree":
+ ns["test_NodeGroup_%s" % t] = _test_id_gen("node_groups", args_create=(DUMMY_NAME, t))
+for t in bpy.data.textures.bl_rna.functions["new"].parameters["type"].enum_items.keys():
+ ns["test_Texture_%s" % t] = _test_id_gen("textures", args_create=(DUMMY_NAME, t))
+del ns
+
+
+def main():
+ for fn_id, fn_val in sorted(globals().items()):
+ if fn_id.startswith("test_") and callable(fn_val):
+ fn_val(fn_id)
+
+ print("Error (total): %d" % GLOBALS["error_num"])
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/python/bl_rna_wiki_reference.py b/tests/python/bl_rna_manual_reference.py
index 5781c53c045..c67b6c1532b 100644
--- a/tests/python/bl_rna_wiki_reference.py
+++ b/tests/python/bl_rna_manual_reference.py
@@ -18,8 +18,8 @@
# <pep8 compliant>
-# Use for validating our wiki interlinking.
-# ./blender.bin --background -noaudio --python tests/python/bl_rna_wiki_reference.py
+# Use for validating our manual interlinking.
+# ./blender.bin --background -noaudio --python tests/python/bl_rna_manual_reference.py
#
# 1) test_data() -- ensure the data we have is correct format
# 2) test_lookup_coverage() -- ensure that we have lookups for _every_ RNA path
@@ -31,10 +31,10 @@ import bpy
def test_data():
- import rna_wiki_reference
+ import rna_manual_reference
- assert(isinstance(rna_wiki_reference.url_manual_mapping, tuple))
- for i, value in enumerate(rna_wiki_reference.url_manual_mapping):
+ assert(isinstance(rna_manual_reference.url_manual_mapping, tuple))
+ for i, value in enumerate(rna_manual_reference.url_manual_mapping):
try:
assert(len(value) == 2)
assert(isinstance(value[0], str))
@@ -92,14 +92,19 @@ def test_language_coverage():
def test_urls():
+ import os
import sys
- import rna_wiki_reference
+ import rna_manual_reference
import urllib.error
from urllib.request import urlopen
- prefix = rna_wiki_reference.url_manual_prefix
- urls = {suffix for (rna_id, suffix) in rna_wiki_reference.url_manual_mapping}
+ # avoid URL lookups if possible
+ LOCAL_PREFIX = os.environ.get("LOCAL_PREFIX")
+ if LOCAL_PREFIX is None:
+ prefix = rna_manual_reference.url_manual_prefix
+
+ urls = {suffix for (rna_id, suffix) in rna_manual_reference.url_manual_mapping}
urls_len = "%d" % len(urls)
print("")
@@ -113,16 +118,26 @@ def test_urls():
urls_fail = []
- for url in sorted(urls):
- url_full = prefix + url
- print(" %s ... " % url_full, end="")
- sys.stdout.flush()
- try:
- urlopen(url_full)
- print(color_green + "OK" + color_normal)
- except urllib.error.HTTPError:
- print(color_red + "FAIL!" + color_normal)
- urls_fail.append(url)
+ if LOCAL_PREFIX:
+ for url in sorted(urls):
+ url_full = os.path.join(LOCAL_PREFIX, url.partition("#")[0])
+ print(" %s ... " % url_full, end="")
+ if os.path.exists(url_full):
+ print(color_green + "OK" + color_normal)
+ else:
+ print(color_red + "FAIL!" + color_normal)
+ urls_fail.append(url)
+ else:
+ for url in sorted(urls):
+ url_full = prefix + url
+ print(" %s ... " % url_full, end="")
+ sys.stdout.flush()
+ try:
+ urlopen(url_full)
+ print(color_green + "OK" + color_normal)
+ except urllib.error.HTTPError:
+ print(color_red + "FAIL!" + color_normal)
+ urls_fail.append(url)
if urls_fail:
urls_len = "%d" % len(urls_fail)
diff --git a/tests/python/bl_rst_completeness.py b/tests/python/bl_rst_completeness.py
index d0ba2c552cf..d8dfac66d13 100644
--- a/tests/python/bl_rst_completeness.py
+++ b/tests/python/bl_rst_completeness.py
@@ -62,7 +62,7 @@ def is_directive_pydata(filepath, directive):
return True
elif directive.type in {"module", "note", "warning", "code-block", "hlist", "seealso"}:
return False
- elif directive.type in {"literalinclude"}: # TODO
+ elif directive.type == "literalinclude": # TODO
return False
else:
print(directive_to_str(filepath, directive), end=" ")
diff --git a/tests/python/bl_run_operators.py b/tests/python/bl_run_operators.py
index f7fafe833aa..f3c553cf3ef 100644
--- a/tests/python/bl_run_operators.py
+++ b/tests/python/bl_run_operators.py
@@ -34,6 +34,10 @@ RANDOM_SEED = [1] # so we can redo crashes
RANDOM_RESET = 0.1 # 10% chance of resetting on each new operator
RANDOM_MULTIPLY = 10
+STATE = {
+ "counter": 0,
+ }
+
op_blacklist = (
"script.reload",
@@ -75,6 +79,7 @@ op_blacklist = (
"wm.properties_context_change",
"wm.operator_cheat_sheet",
"wm.interface_theme_*",
+ "wm.previews_ensure", # slow - but harmless
"wm.appconfig_*", # just annoying - but harmless
"wm.keyitem_add", # just annoying - but harmless
"wm.keyconfig_activate", # just annoying - but harmless
@@ -158,7 +163,7 @@ if USE_ATTRSET:
if issubclass(cls, skip_classes):
continue
- ## to support skip-save we cant get all props
+ # # to support skip-save we cant get all props
# properties = cls.bl_rna.properties.keys()
properties = []
for prop_id, prop in cls.bl_rna.properties.items():
@@ -248,7 +253,8 @@ def run_ops(operators, setup_func=None, reset=True):
# first invoke
for op_id, op in operators:
if op.poll():
- print(" operator:", op_id)
+ print(" operator: %4d, %s" % (STATE["counter"], op_id))
+ STATE["counter"] += 1
sys.stdout.flush() # in case of crash
# disable will get blender in a bad state and crash easy!
diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py
new file mode 100755
index 00000000000..36fad175cfa
--- /dev/null
+++ b/tests/python/cycles_render_tests.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python3
+# Apache License, Version 2.0
+
+import argparse
+import os
+import subprocess
+import sys
+import tempfile
+
+
+def render_file(filepath):
+ command = (
+ BLENDER,
+ "--background",
+ "-noaudio",
+ "--factory-startup",
+ filepath,
+ "-E", "CYCLES",
+ "-o", TEMP_FILE_MASK,
+ "-F", "PNG",
+ "-f", "1",
+ )
+ try:
+ output = subprocess.check_output(command)
+ if VERBOSE:
+ print(output.decode("utf-8"))
+ return None
+ except subprocess.CalledProcessError as e:
+ if os.path.exists(TEMP_FILE):
+ os.remove(TEMP_FILE)
+ if VERBOSE:
+ print(e.output.decode("utf-8"))
+ if b"Error: engine not found" in e.output:
+ return "NO_CYCLES"
+ elif b"blender probably wont start" in e.output:
+ return "NO_START"
+ return "CRASH"
+ except:
+ if os.path.exists(TEMP_FILE):
+ os.remove(TEMP_FILE)
+ if VERBOSE:
+ print(e.output.decode("utf-8"))
+ return "CRASH"
+
+
+def test_get_name(filepath):
+ filename = os.path.basename(filepath)
+ return os.path.splitext(filename)[0]
+
+
+def verify_output(filepath):
+ testname = test_get_name(filepath)
+ dirpath = os.path.dirname(filepath)
+ reference_dirpath = os.path.join(dirpath, "reference_renders")
+ reference_image = os.path.join(reference_dirpath, testname + ".png")
+ if not os.path.exists(reference_image):
+ return False
+ command = (
+ IDIFF,
+ "-fail", "0.01",
+ "-failpercent", "1",
+ reference_image,
+ TEMP_FILE,
+ )
+ try:
+ subprocess.check_output(command)
+ return True
+ except subprocess.CalledProcessError as e:
+ if VERBOSE:
+ print(e.output.decode("utf-8"))
+ return e.returncode == 1
+
+
+def run_test(filepath):
+ testname = test_get_name(filepath)
+ spacer = "." * (32 - len(testname))
+ print(testname, spacer, end="")
+ sys.stdout.flush()
+ error = render_file(filepath)
+ if not error:
+ if verify_output(filepath):
+ print("PASS")
+ else:
+ error = "VERIFY"
+ if error:
+ print("FAIL", error)
+ return error
+
+
+def blend_list(path):
+ for dirpath, dirnames, filenames in os.walk(path):
+ for filename in filenames:
+ if filename.lower().endswith(".blend"):
+ filepath = os.path.join(dirpath, filename)
+ yield filepath
+
+
+def run_all_tests(dirpath):
+ failed_tests = []
+ all_files = list(blend_list(dirpath))
+ all_files.sort()
+ for filepath in all_files:
+ error = run_test(filepath)
+ if error:
+ if error == "NO_CYCLES":
+ print("Can't perform tests because Cycles failed to load!")
+ return False
+ elif error == "NO_START":
+ print('Can not perform tests because blender fails to start.',
+ 'Make sure INSTALL target was run.')
+ return False
+ elif error == 'VERIFY':
+ pass
+ else:
+ print("Unknown error %r" % error)
+ testname = test_get_name(filepath)
+ failed_tests.append(testname)
+ if failed_tests:
+ failed_tests.sort()
+ print("\n\nFAILED tests:")
+ for test in failed_tests:
+ print(" ", test)
+ return False
+ return True
+
+
+def create_argparse():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-blender", nargs="+")
+ parser.add_argument("-testdir", nargs=1)
+ parser.add_argument("-idiff", nargs=1)
+ return parser
+
+
+def main():
+ parser = create_argparse()
+ args = parser.parse_args()
+
+ global BLENDER, ROOT, IDIFF
+ global TEMP_FILE, TEMP_FILE_MASK, TEST_SCRIPT
+ global VERBOSE
+
+ BLENDER = args.blender[0]
+ ROOT = args.testdir[0]
+ IDIFF = args.idiff[0]
+
+ TEMP = tempfile.mkdtemp()
+ TEMP_FILE_MASK = os.path.join(TEMP, "test")
+ TEMP_FILE = TEMP_FILE_MASK + "0001.png"
+
+ TEST_SCRIPT = os.path.join(os.path.dirname(__file__), "runtime_check.py")
+
+ VERBOSE = os.environ.get("BLENDER_VERBOSE") is not None
+
+ ok = run_all_tests(ROOT)
+
+ # Cleanup temp files and folders
+ if os.path.exists(TEMP_FILE):
+ os.remove(TEMP_FILE)
+ os.rmdir(TEMP)
+
+ sys.exit(not ok)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/python/pep8.py b/tests/python/pep8.py
index 7713ffeaaa4..0d6db729767 100644
--- a/tests/python/pep8.py
+++ b/tests/python/pep8.py
@@ -95,19 +95,40 @@ def main():
print(" %s" % f)
# strict imports
- print("\n\n\n# running pep8...")
+ print("\n\n\n# checking imports...")
import re
import_check = re.compile(r"\s*from\s+[A-z\.]+\s+import \*\s*")
for f, pep8_type in files:
for i, l in enumerate(open(f, 'r', encoding='utf8')):
if import_check.match(l):
print("%s:%d:0: global import bad practice" % (f, i + 1))
+ del re, import_check
+
+ print("\n\n\n# checking class definitions...")
+ import re
+ class_check = re.compile(r"\s*class\s+.*\(\):.*")
+ for f, pep8_type in files:
+ for i, l in enumerate(open(f, 'r', encoding='utf8')):
+ if class_check.match(l):
+ print("%s:%d:0: empty class (), remove" % (f, i + 1))
+ del re, class_check
print("\n\n\n# running pep8...")
# these are very picky and often hard to follow
# while keeping common script formatting.
- ignore = "E122", "E123", "E124", "E125", "E126", "E127", "E128"
+ ignore = (
+ "E122",
+ "E123",
+ "E124",
+ "E125",
+ "E126",
+ "E127",
+ "E128",
+ # "imports not at top of file."
+ # prefer to load as needed (lazy load addons etc).
+ "E402",
+ )
for f, pep8_type in files:
diff --git a/tests/python/rst_to_doctree_mini.py b/tests/python/rst_to_doctree_mini.py
index 6a885a108f8..dfc6cd57db6 100644
--- a/tests/python/rst_to_doctree_mini.py
+++ b/tests/python/rst_to_doctree_mini.py
@@ -28,13 +28,14 @@
import collections
-Directive = collections.namedtuple('Directive',
- ("type",
- "value",
- "value_strip",
- "line",
- "indent",
- "members"))
+Directive = collections.namedtuple(
+ "Directive",
+ ("type",
+ "value",
+ "value_strip",
+ "line",
+ "indent",
+ "members"))
def parse_rst_py(filepath):
@@ -80,7 +81,7 @@ def parse_rst_py(filepath):
return tree[0]
-if __name__ == "__main__":
+def main():
# not intended use, but may as well print rst files passed as a test.
import sys
for arg in sys.argv:
@@ -88,3 +89,7 @@ if __name__ == "__main__":
items = parse_rst_py(arg)
for i in items:
print(i)
+
+
+if __name__ == "__main__":
+ main()