Selaa lähdekoodia

[add] levenshtein unit tests

isundil 9 vuotta sitten
vanhempi
commit
b76c7d26df

+ 1 - 0
.gitignore

@@ -38,6 +38,7 @@
 /test/json_test
 /test/wrapped_test
 /test/optional_test
+/test/levenshtein_test
 /cmake_install.cmake
 /Makefile
 .fuse_hidden*

+ 13 - 0
CMakeLists.txt

@@ -23,6 +23,7 @@ add_executable(jsonstroll
     src/streamConsumer.cpp
     src/searchPattern.cpp
     src/inputSequence.cpp
+    src/levenshtein.cpp
 
     src/jsonElement.cpp
     src/jsonArray.cpp
@@ -48,6 +49,7 @@ add_executable(json_test
     src/warning.cpp
     src/linearHistory.cpp
     src/searchPattern.cpp
+    src/levenshtein.cpp
     src/streamConsumer.cpp
     src/jsonArray.cpp
     src/jsonObjectEntry.cpp
@@ -80,6 +82,17 @@ set_property(
     PROPERTY RUNTIME_OUTPUT_DIRECTORY test
     )
 
+add_executable(levenshtein_test
+    src/levenshtein.cpp
+
+    test/src/levenshtein_test.cpp
+    )
+add_test(levenshtein_test test/levenshtein_test)
+set_property(
+    TARGET levenshtein_test
+    PROPERTY RUNTIME_OUTPUT_DIRECTORY test
+    )
+
 # Add manual page
 find_program (HELP2MAN help2man)
 add_custom_target(man ALL)

+ 2 - 0
include/jsonElement.hh

@@ -22,6 +22,8 @@ class JSonElement
         **/
         virtual std::string stringify() const =0;
 
+        virtual float diff(const JSonElement &) const;
+
         /**
          * get the number of col string will output
         **/

+ 8 - 0
include/levenshtein.hh

@@ -0,0 +1,8 @@
+#pragma once
+
+#include <string>
+
+unsigned int levenshtein(const char *a, const size_t lenA, const char *b, const size_t lenB);
+unsigned int levenshtein(const std::string &a, const std::string &b);
+float levenshteinPercent(const std::string &strA, const std::string &strB);
+

+ 6 - 0
src/jsonElement.cpp

@@ -8,6 +8,7 @@
 #include "jsonContainer.hh"
 #include "jsonObjectEntry.hh"
 #include "searchPattern.hh"
+#include "levenshtein.hh"
 
 JSonElement::JSonElement(JSonElement *p): parent(p), _strlen(0)
 { }
@@ -107,3 +108,8 @@ bool JSonElement::match(const SearchPattern &searchPattern) const
     return searchPattern.match(stringify(), this);
 }
 
+float JSonElement::diff(const JSonElement &o) const
+{
+    return levenshteinPercent(stringify(), o.stringify());
+}
+

+ 31 - 0
src/levenshtein.cpp

@@ -0,0 +1,31 @@
+#include "levenshtein.hh"
+
+unsigned int levenshtein(const char *a, const size_t lenA, const char *b, const size_t lenB)
+{
+    int **matrice = new int*[lenA]();
+    matrice[0] = new int[lenB]();
+    for (size_t j=0; j < lenB; j++)
+        matrice[0][j] = j;
+    for (size_t i=1; i < lenA; ++i)
+    {
+        matrice[i] = new int[lenB]();
+        matrice[i][0] = i;
+        for (size_t j=1; j < lenB; ++j)
+            matrice[i][j] = std::min(std::min(
+                    matrice[i -1][j] +1,
+                    matrice[i][j -1] +1),
+                    matrice[i -1][j -1] + (a[i] == b[j] ? 0 : 1));
+    }
+    return matrice[lenA -1][lenB -1];
+}
+
+unsigned int levenshtein(const std::string &strA, const std::string &strB)
+{
+    return levenshtein(strA.c_str(), strA.size(), strB.c_str(), strB.size());
+}
+
+float levenshteinPercent(const std::string &strA, const std::string &strB)
+{
+    return 1 - (levenshtein(strA, strB) / std::max(strA.size(), strB.size()));
+}
+

+ 35 - 0
test/src/levenshtein_test.cpp

@@ -0,0 +1,35 @@
+#include <iostream>
+#include "levenshtein.hh"
+
+#define FAILED(got, op, expt) {std::cout << __FILE__ << ":" << __LINE__ << ": failed asserting " << got << " " << op << " expected " << expt << std::endl; return false; }
+
+bool doTest()
+{
+    float pc;
+    unsigned int lev;
+
+    if ((lev = levenshtein("coucou", "coucou")) != 0)
+        FAILED(lev, "!=", 0);
+    if ((pc = levenshteinPercent("coucou", "coucou")) != 1)
+        FAILED(pc, "!=", 1);
+    if ((lev = levenshtein("coocou", "coucou")) != 1)
+        FAILED(lev, "!=", 1);
+    if ((lev = levenshtein("abcdefghijk", "zabcdefghijk")) != 1)
+        FAILED(lev, "!=", 1);
+    if ((lev = levenshtein("zabcdefghijk", "abcdefghijk")) != 1)
+        FAILED(lev, "!=", 1);
+    if ((lev = levenshtein("zabcdefghijk", "zabcdkfghijk")) != 1)
+        FAILED(lev, "!=", 1);
+    if ((lev = levenshtein("a", "zabcdkfghijk")) != 11)
+        FAILED(lev, "!=", 11);
+    return true;
+}
+
+int main()
+{
+    if (!doTest())
+        exit(EXIT_FAILURE);
+    exit(EXIT_SUCCESS);
+}
+
+

+ 1 - 0
test/testArray1.json

@@ -0,0 +1 @@
+[ 1, 2, 4, 4, 9, 37, 12, 24, 54, 19, 22 ]

+ 1 - 0
test/testArray2.json

@@ -0,0 +1 @@
+[ 1, 2, 5, 4, 42, 37, 12, 24, 21, 54, 19, 22 ]