test: 增加ocr接口的单元测试
Description: 增加ocr接口的单元测试 Log: no Change-Id: Ie78bb8f8d2def33ce441857daef52bdc4efa5650
This commit is contained in:
parent
c2f16bd20e
commit
facb87f672
280
3rdparty/stub_linux/addr_any.h
vendored
Executable file
280
3rdparty/stub_linux/addr_any.h
vendored
Executable file
|
@ -0,0 +1,280 @@
|
||||||
|
#ifndef __ADDR_ANY_H__
|
||||||
|
#define __ADDR_ANY_H__
|
||||||
|
|
||||||
|
|
||||||
|
//linux
|
||||||
|
#include <regex.h>
|
||||||
|
#include <cxxabi.h>
|
||||||
|
//c
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
//c++
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
//project
|
||||||
|
#include "elfio.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class AddrAny
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AddrAny()
|
||||||
|
{
|
||||||
|
m_init = get_exe_pathname(m_fullname);
|
||||||
|
m_baseaddr = 0;
|
||||||
|
}
|
||||||
|
AddrAny(std::string libname)
|
||||||
|
{
|
||||||
|
m_init = get_lib_pathname_and_baseaddr(libname, m_fullname, m_baseaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_local_func_addr_symtab(std::string func_name_regex_str, std::map<std::string,void*>& result)
|
||||||
|
{
|
||||||
|
return get_func_addr(SHT_SYMTAB, STB_LOCAL, func_name_regex_str, result);
|
||||||
|
}
|
||||||
|
int get_global_func_addr_symtab(std::string func_name_regex_str, std::map<std::string,void*>& result)
|
||||||
|
{
|
||||||
|
return get_func_addr(SHT_SYMTAB, STB_GLOBAL, func_name_regex_str, result);
|
||||||
|
}
|
||||||
|
int get_weak_func_addr_symtab(std::string func_name_regex_str, std::map<std::string,void*>& result)
|
||||||
|
{
|
||||||
|
return get_func_addr(SHT_SYMTAB, STB_WEAK, func_name_regex_str, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_global_func_addr_dynsym( std::string func_name_regex_str, std::map<std::string,void*>& result)
|
||||||
|
{
|
||||||
|
return get_func_addr(SHT_DYNSYM, STB_GLOBAL, func_name_regex_str, result);
|
||||||
|
}
|
||||||
|
int get_weak_func_addr_dynsym(std::string func_name_regex_str, std::map<std::string,void*>& result)
|
||||||
|
{
|
||||||
|
return get_func_addr(SHT_DYNSYM, STB_WEAK, func_name_regex_str, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool demangle(std::string& s, std::string& name) {
|
||||||
|
int status;
|
||||||
|
char* pname = abi::__cxa_demangle(s.c_str(), 0, 0, &status);
|
||||||
|
if (status != 0)
|
||||||
|
{
|
||||||
|
switch(status)
|
||||||
|
{
|
||||||
|
case -1: name = "memory allocation error"; break;
|
||||||
|
case -2: name = "invalid name given"; break;
|
||||||
|
case -3: name = "internal error: __cxa_demangle: invalid argument"; break;
|
||||||
|
default: name = "unknown error occured"; break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
name = pname;
|
||||||
|
free(pname);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool get_exe_pathname( std::string& name)
|
||||||
|
{
|
||||||
|
char line[512];
|
||||||
|
FILE *fp;
|
||||||
|
uintptr_t base_addr;
|
||||||
|
char perm[5];
|
||||||
|
unsigned long offset;
|
||||||
|
int pathname_pos;
|
||||||
|
char *pathname;
|
||||||
|
size_t pathname_len;
|
||||||
|
int match = 0;
|
||||||
|
|
||||||
|
if(NULL == (fp = fopen("/proc/self/maps", "r")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(fgets(line, sizeof(line), fp))
|
||||||
|
{
|
||||||
|
if(sscanf(line, "%" PRIxPTR "-%*lx %4s %lx %*x:%*x %*d%n", &base_addr, perm, &offset, &pathname_pos) != 3) continue;
|
||||||
|
|
||||||
|
if(0 != offset) continue;
|
||||||
|
|
||||||
|
//get pathname
|
||||||
|
while(isspace(line[pathname_pos]) && pathname_pos < (int)(sizeof(line) - 1))
|
||||||
|
pathname_pos += 1;
|
||||||
|
if(pathname_pos >= (int)(sizeof(line) - 1)) continue;
|
||||||
|
pathname = line + pathname_pos;
|
||||||
|
pathname_len = strlen(pathname);
|
||||||
|
if(0 == pathname_len) continue;
|
||||||
|
if(pathname[pathname_len - 1] == '\n')
|
||||||
|
{
|
||||||
|
pathname[pathname_len - 1] = '\0';
|
||||||
|
pathname_len -= 1;
|
||||||
|
}
|
||||||
|
if(0 == pathname_len) continue;
|
||||||
|
if('[' == pathname[0]) continue;
|
||||||
|
|
||||||
|
name = pathname;
|
||||||
|
match = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if(0 == match)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool get_lib_pathname_and_baseaddr(std::string pathname_regex_str, std::string& name, unsigned long& addr)
|
||||||
|
{
|
||||||
|
char line[512];
|
||||||
|
FILE *fp;
|
||||||
|
uintptr_t base_addr;
|
||||||
|
char perm[5];
|
||||||
|
unsigned long offset;
|
||||||
|
int pathname_pos;
|
||||||
|
char *pathname;
|
||||||
|
size_t pathname_len;
|
||||||
|
int match;
|
||||||
|
regex_t pathname_regex;
|
||||||
|
|
||||||
|
regcomp(&pathname_regex, pathname_regex_str.c_str(), 0);
|
||||||
|
|
||||||
|
if(NULL == (fp = fopen("/proc/self/maps", "r")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(fgets(line, sizeof(line), fp))
|
||||||
|
{
|
||||||
|
if(sscanf(line, "%" PRIxPTR "-%*lx %4s %lx %*x:%*x %*d%n", &base_addr, perm, &offset, &pathname_pos) != 3) continue;
|
||||||
|
|
||||||
|
//check permission
|
||||||
|
if(perm[0] != 'r') continue;
|
||||||
|
if(perm[3] != 'p') continue; //do not touch the shared memory
|
||||||
|
|
||||||
|
//check offset
|
||||||
|
//
|
||||||
|
//We are trying to find ELF header in memory.
|
||||||
|
//It can only be found at the beginning of a mapped memory regions
|
||||||
|
//whose offset is 0.
|
||||||
|
if(0 != offset) continue;
|
||||||
|
|
||||||
|
//get pathname
|
||||||
|
while(isspace(line[pathname_pos]) && pathname_pos < (int)(sizeof(line) - 1))
|
||||||
|
pathname_pos += 1;
|
||||||
|
if(pathname_pos >= (int)(sizeof(line) - 1)) continue;
|
||||||
|
pathname = line + pathname_pos;
|
||||||
|
pathname_len = strlen(pathname);
|
||||||
|
if(0 == pathname_len) continue;
|
||||||
|
if(pathname[pathname_len - 1] == '\n')
|
||||||
|
{
|
||||||
|
pathname[pathname_len - 1] = '\0';
|
||||||
|
pathname_len -= 1;
|
||||||
|
}
|
||||||
|
if(0 == pathname_len) continue;
|
||||||
|
if('[' == pathname[0]) continue;
|
||||||
|
|
||||||
|
//check pathname
|
||||||
|
//if we need to hook this elf?
|
||||||
|
match = 0;
|
||||||
|
if(0 == regexec(&pathname_regex, pathname, 0, NULL, 0))
|
||||||
|
{
|
||||||
|
match = 1;
|
||||||
|
name = pathname;
|
||||||
|
addr = (unsigned long)base_addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(0 == match) continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
if(0 == match)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_func_addr(unsigned int ttype, unsigned int stype, std::string& func_name_regex_str, std::map<std::string,void*>& result)
|
||||||
|
{
|
||||||
|
// Create an elfio reader
|
||||||
|
ELFIO::elfio reader;
|
||||||
|
int count = 0;
|
||||||
|
regex_t pathname_regex;
|
||||||
|
|
||||||
|
if(!m_init)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
regcomp(&pathname_regex, func_name_regex_str.c_str(), 0);
|
||||||
|
// Load ELF data
|
||||||
|
if(!reader.load(m_fullname.c_str()))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ELFIO::Elf_Half sec_num = reader.sections.size();
|
||||||
|
for(int i = 0; i < sec_num; ++i)
|
||||||
|
{
|
||||||
|
ELFIO::section* psec = reader.sections[i];
|
||||||
|
// Check section type
|
||||||
|
if(psec->get_type() == ttype)
|
||||||
|
{
|
||||||
|
const ELFIO::symbol_section_accessor symbols( reader, psec );
|
||||||
|
for ( unsigned int j = 0; j < symbols.get_symbols_num(); ++j )
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string name_mangle;
|
||||||
|
ELFIO::Elf64_Addr value;
|
||||||
|
ELFIO::Elf_Xword size;
|
||||||
|
unsigned char bind;
|
||||||
|
unsigned char type;
|
||||||
|
ELFIO::Elf_Half section_index;
|
||||||
|
unsigned char other;
|
||||||
|
|
||||||
|
// Read symbol properties
|
||||||
|
symbols.get_symbol( j, name, value, size, bind, type, section_index, other );
|
||||||
|
if(type == STT_FUNC && bind == stype)
|
||||||
|
{
|
||||||
|
bool ret = demangle(name,name_mangle);
|
||||||
|
if(ret == true)
|
||||||
|
{
|
||||||
|
if (0 == regexec(&pathname_regex, name_mangle.c_str(), 0, NULL, 0))
|
||||||
|
{
|
||||||
|
result.insert ( std::pair<std::string,void *>(name_mangle,(void*)(value + m_baseaddr)));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (0 == regexec(&pathname_regex, name.c_str(), 0, NULL, 0))
|
||||||
|
{
|
||||||
|
result.insert ( std::pair<std::string,void *>(name,(void*)(value + m_baseaddr)));
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool m_init;
|
||||||
|
std::string m_name;
|
||||||
|
std::string m_fullname;
|
||||||
|
unsigned long m_baseaddr;
|
||||||
|
|
||||||
|
};
|
||||||
|
#endif
|
177
3rdparty/stub_linux/addr_pri.h
vendored
Executable file
177
3rdparty/stub_linux/addr_pri.h
vendored
Executable file
|
@ -0,0 +1,177 @@
|
||||||
|
#ifndef __ADDR_PRI_H__
|
||||||
|
#define __ADDR_PRI_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//base on C++11
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
access private function
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <bool B, class T = void>
|
||||||
|
using enable_if_t = typename enable_if<B, T>::type;
|
||||||
|
template <class T>
|
||||||
|
using remove_reference_t = typename remove_reference<T>::type;
|
||||||
|
} // std
|
||||||
|
|
||||||
|
// Unnamed namespace is used to avoid duplicate symbols if the macros are used
|
||||||
|
namespace {
|
||||||
|
namespace private_access_detail {
|
||||||
|
|
||||||
|
// @tparam TagType, used to declare different "get" funciton overloads for
|
||||||
|
// different members/statics
|
||||||
|
template <typename PtrType, PtrType PtrValue, typename TagType>
|
||||||
|
struct private_access {
|
||||||
|
// Normal lookup cannot find in-class defined (inline) friend functions.
|
||||||
|
friend PtrType get(TagType) { return PtrValue; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace private_access_detail
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Used macro naming conventions:
|
||||||
|
// The "namespace" of this macro library is PRIVATE_ACCESS, i.e. all
|
||||||
|
// macro here has this prefix.
|
||||||
|
// All implementation macro, which are not meant to be used directly have the
|
||||||
|
// PRIVATE_ACCESS_DETAIL prefix.
|
||||||
|
// Some macros have the ABCD_IMPL form, which means they contain the
|
||||||
|
// implementation details for the specific ABCD macro.
|
||||||
|
|
||||||
|
#define PRIVATE_ACCESS_DETAIL_CONCATENATE_IMPL(x, y) x##y
|
||||||
|
#define PRIVATE_ACCESS_DETAIL_CONCATENATE(x, y) \
|
||||||
|
PRIVATE_ACCESS_DETAIL_CONCATENATE_IMPL(x, y)
|
||||||
|
|
||||||
|
// @param PtrTypeKind E.g if we have "class A", then it can be "A::*" in case of
|
||||||
|
// members, or it can be "*" in case of statics.
|
||||||
|
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, \
|
||||||
|
PtrTypeKind) \
|
||||||
|
namespace { \
|
||||||
|
namespace private_access_detail { \
|
||||||
|
/* Tag type, used to declare different get funcitons for different \
|
||||||
|
* members \
|
||||||
|
*/ \
|
||||||
|
struct Tag {}; \
|
||||||
|
/* Explicit instantiation */ \
|
||||||
|
template struct private_access<decltype(&Class::Name), &Class::Name, \
|
||||||
|
Tag>; \
|
||||||
|
/* We can build the PtrType only with two aliases */ \
|
||||||
|
/* E.g. using PtrType = int(int) *; would be illformed */ \
|
||||||
|
using PRIVATE_ACCESS_DETAIL_CONCATENATE(Alias_, Tag) = Type; \
|
||||||
|
using PRIVATE_ACCESS_DETAIL_CONCATENATE(PtrType_, Tag) = \
|
||||||
|
PRIVATE_ACCESS_DETAIL_CONCATENATE(Alias_, Tag) PtrTypeKind; \
|
||||||
|
/* Declare the friend function, now it is visible in namespace scope. \
|
||||||
|
* Note, \
|
||||||
|
* we could declare it inside the Tag type too, in that case ADL would \
|
||||||
|
* find \
|
||||||
|
* the declaration. By choosing to declare it here, the Tag type remains \
|
||||||
|
* a \
|
||||||
|
* simple tag type, it has no other responsibilities. */ \
|
||||||
|
PRIVATE_ACCESS_DETAIL_CONCATENATE(PtrType_, Tag) get(Tag); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FIELD(Tag, Class, Type, Name) \
|
||||||
|
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, Class::*) \
|
||||||
|
namespace { \
|
||||||
|
namespace access_private_field { \
|
||||||
|
Type &Class##Name(Class &&t) { return t.*get(private_access_detail::Tag{}); } \
|
||||||
|
Type &Class##Name(Class &t) { return t.*get(private_access_detail::Tag{}); } \
|
||||||
|
/* The following usings are here to avoid duplicate const qualifier \
|
||||||
|
* warnings \
|
||||||
|
*/ \
|
||||||
|
using PRIVATE_ACCESS_DETAIL_CONCATENATE(X, Tag) = Type; \
|
||||||
|
using PRIVATE_ACCESS_DETAIL_CONCATENATE(Y, Tag) = \
|
||||||
|
const PRIVATE_ACCESS_DETAIL_CONCATENATE(X, Tag); \
|
||||||
|
PRIVATE_ACCESS_DETAIL_CONCATENATE(Y, Tag) & Class##Name(const Class &t) {\
|
||||||
|
return t.*get(private_access_detail::Tag{}); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FUN(Tag, Class, Type, Name) \
|
||||||
|
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, Class::*) \
|
||||||
|
namespace { \
|
||||||
|
namespace call_private_fun { \
|
||||||
|
/* We do perfect forwarding, but we want to restrict the overload set \
|
||||||
|
* only for objects which have the type Class. */ \
|
||||||
|
template <typename Obj, \
|
||||||
|
std::enable_if_t<std::is_same<std::remove_reference_t<Obj>, \
|
||||||
|
Class>::value> * = nullptr, \
|
||||||
|
typename... Args> \
|
||||||
|
auto Class##Name(Obj &&o, Args &&... args) -> decltype( \
|
||||||
|
(std::forward<Obj>(o).* \
|
||||||
|
get(private_access_detail::Tag{}))(std::forward<Args>(args)...)) { \
|
||||||
|
return (std::forward<Obj>(o).*get(private_access_detail::Tag{}))( \
|
||||||
|
std::forward<Args>(args)...); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
namespace get_private_fun { \
|
||||||
|
auto Class##Name() -> decltype( \
|
||||||
|
get(private_access_detail::Tag{})) { \
|
||||||
|
return (get(private_access_detail::Tag{})); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FIELD(Tag, Class, Type, \
|
||||||
|
Name) \
|
||||||
|
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, *) \
|
||||||
|
namespace { \
|
||||||
|
namespace access_private_static_field { \
|
||||||
|
namespace Class { \
|
||||||
|
Type &Class##Name() { return *get(private_access_detail::Tag{}); } \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FUN(Tag, Class, Type, \
|
||||||
|
Name) \
|
||||||
|
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE(Tag, Class, Type, Name, *) \
|
||||||
|
namespace { \
|
||||||
|
namespace call_private_static_fun { \
|
||||||
|
namespace Class { \
|
||||||
|
template <typename... Args> \
|
||||||
|
auto Class##Name(Args &&... args) -> decltype( \
|
||||||
|
get(private_access_detail::Tag{})(std::forward<Args>(args)...)) { \
|
||||||
|
return get(private_access_detail::Tag{})( \
|
||||||
|
std::forward<Args>(args)...); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
namespace get_private_static_fun { \
|
||||||
|
namespace Class { \
|
||||||
|
auto Class##Name() -> decltype(get(private_access_detail::Tag{})) { \
|
||||||
|
return get(private_access_detail::Tag{}); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PRIVATE_ACCESS_DETAIL_UNIQUE_TAG \
|
||||||
|
PRIVATE_ACCESS_DETAIL_CONCATENATE(PrivateAccessTag, __COUNTER__)
|
||||||
|
|
||||||
|
#define ACCESS_PRIVATE_FIELD(Class, Type, Name) \
|
||||||
|
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FIELD(PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, \
|
||||||
|
Class, Type, Name)
|
||||||
|
|
||||||
|
#define ACCESS_PRIVATE_FUN(Class, Type, Name) \
|
||||||
|
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_FUN(PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, \
|
||||||
|
Class, Type, Name)
|
||||||
|
|
||||||
|
#define ACCESS_PRIVATE_STATIC_FIELD(Class, Type, Name) \
|
||||||
|
Type Class::Name; \
|
||||||
|
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FIELD( \
|
||||||
|
PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, Class, Type, Name)
|
||||||
|
|
||||||
|
#define ACCESS_PRIVATE_STATIC_FUN(Class, Type, Name) \
|
||||||
|
PRIVATE_ACCESS_DETAIL_ACCESS_PRIVATE_STATIC_FUN( \
|
||||||
|
PRIVATE_ACCESS_DETAIL_UNIQUE_TAG, Class, Type, Name)
|
||||||
|
|
||||||
|
#endif
|
4888
3rdparty/stub_linux/elfio.hpp
vendored
Executable file
4888
3rdparty/stub_linux/elfio.hpp
vendored
Executable file
File diff suppressed because it is too large
Load Diff
281
3rdparty/stub_linux/stub.h
vendored
Executable file
281
3rdparty/stub_linux/stub.h
vendored
Executable file
|
@ -0,0 +1,281 @@
|
||||||
|
#ifndef __STUB_H__
|
||||||
|
#define __STUB_H__
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
//windows
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
//linux
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
//c
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
//c++
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
#define ADDR(CLASS_NAME,MEMBER_NAME) (&CLASS_NAME::MEMBER_NAME)
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
replace function
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||||
|
#define CODESIZE 16U
|
||||||
|
#define CODESIZE_MIN 16U
|
||||||
|
#define CODESIZE_MAX CODESIZE
|
||||||
|
// ldr x9, +8
|
||||||
|
// br x9
|
||||||
|
// addr
|
||||||
|
#define REPLACE_FAR(t, fn, fn_stub)\
|
||||||
|
((uint32_t*)fn)[0] = 0x58000040 | 9;\
|
||||||
|
((uint32_t*)fn)[1] = 0xd61f0120 | (9 << 5);\
|
||||||
|
*(long long *)(fn + 8) = (long long )fn_stub;
|
||||||
|
#define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub)
|
||||||
|
#elif defined(__arm__) || defined(_M_ARM)
|
||||||
|
#define CODESIZE 8U
|
||||||
|
#define CODESIZE_MIN 8U
|
||||||
|
#define CODESIZE_MAX CODESIZE
|
||||||
|
// ldr pc, [pc, #-4]
|
||||||
|
#define REPLACE_FAR(t, fn, fn_stub)\
|
||||||
|
((uint32_t*)fn)[0] = 0xe51ff004;\
|
||||||
|
((uint32_t*)fn)[1] = (uint32_t)fn_stub;
|
||||||
|
#define REPLACE_NEAR(t, fn, fn_stub) REPLACE_FAR(t, fn, fn_stub)
|
||||||
|
#elif defined(__thumb__) || defined(_M_THUMB)
|
||||||
|
#error "Thumb is not supported"
|
||||||
|
#else //__i386__ _x86_64__
|
||||||
|
#define CODESIZE 13U
|
||||||
|
#define CODESIZE_MIN 5U
|
||||||
|
#define CODESIZE_MAX CODESIZE
|
||||||
|
//13 byte(jmp m16:64)
|
||||||
|
//movabs $0x102030405060708,%r11
|
||||||
|
//jmpq *%r11
|
||||||
|
#define REPLACE_FAR(t, fn, fn_stub)\
|
||||||
|
*fn = 0x49;\
|
||||||
|
*(fn + 1) = 0xbb;\
|
||||||
|
*(long long *)(fn + 2) = (long long)fn_stub;\
|
||||||
|
*(fn + 10) = 0x41;\
|
||||||
|
*(fn + 11) = 0xff;\
|
||||||
|
*(fn + 12) = 0xe3;
|
||||||
|
|
||||||
|
//5 byte(jmp rel32)
|
||||||
|
#define REPLACE_NEAR(t, fn, fn_stub)\
|
||||||
|
*fn = 0xE9;\
|
||||||
|
*(int *)(fn + 1) = (int)(fn_stub - fn - CODESIZE_MIN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct func_stub
|
||||||
|
{
|
||||||
|
char *fn;
|
||||||
|
unsigned char code_buf[CODESIZE];
|
||||||
|
bool far_jmp;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Stub
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Stub()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
SYSTEM_INFO sys_info;
|
||||||
|
GetSystemInfo(&sys_info);
|
||||||
|
m_pagesize = sys_info.dwPageSize;
|
||||||
|
#else
|
||||||
|
m_pagesize = sysconf(_SC_PAGE_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (m_pagesize < 0)
|
||||||
|
{
|
||||||
|
m_pagesize = 4096;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~Stub()
|
||||||
|
{
|
||||||
|
std::map<char*,func_stub*>::iterator iter;
|
||||||
|
struct func_stub *pstub;
|
||||||
|
for(iter=m_result.begin(); iter != m_result.end(); iter++)
|
||||||
|
{
|
||||||
|
pstub = iter->second;
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD lpflOldProtect;
|
||||||
|
if(0 != VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect))
|
||||||
|
#else
|
||||||
|
if (0 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
|
if(pstub->far_jmp)
|
||||||
|
{
|
||||||
|
std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MAX);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect);
|
||||||
|
#else
|
||||||
|
mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
iter->second = NULL;
|
||||||
|
delete pstub;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
template<typename T,typename S>
|
||||||
|
void set(T addr, S addr_stub)
|
||||||
|
{
|
||||||
|
char * fn;
|
||||||
|
char * fn_stub;
|
||||||
|
fn = addrof(addr);
|
||||||
|
fn_stub = addrof(addr_stub);
|
||||||
|
struct func_stub *pstub;
|
||||||
|
pstub = new func_stub;
|
||||||
|
//start
|
||||||
|
pstub->fn = fn;
|
||||||
|
|
||||||
|
if(distanceof(fn, fn_stub))
|
||||||
|
{
|
||||||
|
pstub->far_jmp = true;
|
||||||
|
std::memcpy(pstub->code_buf, fn, CODESIZE_MAX);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pstub->far_jmp = false;
|
||||||
|
std::memcpy(pstub->code_buf, fn, CODESIZE_MIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD lpflOldProtect;
|
||||||
|
if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect))
|
||||||
|
#else
|
||||||
|
if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
throw("stub set memory protect to w+r+x faild");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pstub->far_jmp)
|
||||||
|
{
|
||||||
|
REPLACE_FAR(this, fn, fn_stub);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
REPLACE_NEAR(this, fn, fn_stub);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect))
|
||||||
|
#else
|
||||||
|
if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
throw("stub set memory protect to r+x failed");
|
||||||
|
}
|
||||||
|
m_result.insert(std::pair<char*,func_stub*>(fn,pstub));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void reset(T addr)
|
||||||
|
{
|
||||||
|
char * fn;
|
||||||
|
fn = addrof(addr);
|
||||||
|
|
||||||
|
std::map<char*,func_stub*>::iterator iter = m_result.find(fn);
|
||||||
|
|
||||||
|
if (iter == m_result.end())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
struct func_stub *pstub;
|
||||||
|
pstub = iter->second;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD lpflOldProtect;
|
||||||
|
if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READWRITE, &lpflOldProtect))
|
||||||
|
#else
|
||||||
|
if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_WRITE | PROT_EXEC))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
throw("stub reset memory protect to w+r+x faild");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pstub->far_jmp)
|
||||||
|
{
|
||||||
|
std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MAX);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::memcpy(pstub->fn, pstub->code_buf, CODESIZE_MIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if(0 == VirtualProtect(pageof(pstub->fn), m_pagesize * 2, PAGE_EXECUTE_READ, &lpflOldProtect))
|
||||||
|
#else
|
||||||
|
if (-1 == mprotect(pageof(pstub->fn), m_pagesize * 2, PROT_READ | PROT_EXEC))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
throw("stub reset memory protect to r+x failed");
|
||||||
|
}
|
||||||
|
m_result.erase(iter);
|
||||||
|
delete pstub;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
char *pageof(char* addr)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return (char *)((unsigned long long)addr & ~(m_pagesize - 1));
|
||||||
|
#else
|
||||||
|
return (char *)((unsigned long)addr & ~(m_pagesize - 1));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
char* addrof(T addr)
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
T _s;
|
||||||
|
char* _d;
|
||||||
|
}ut;
|
||||||
|
ut._s = addr;
|
||||||
|
return ut._d;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool distanceof(char* addr, char* addr_stub)
|
||||||
|
{
|
||||||
|
std::ptrdiff_t diff = addr_stub >= addr ? addr_stub - addr : addr - addr_stub;
|
||||||
|
if((sizeof(addr) > 4) && (((diff >> 31) - 1) > 0))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef _WIN32
|
||||||
|
//LLP64
|
||||||
|
long long m_pagesize;
|
||||||
|
#else
|
||||||
|
//LP64
|
||||||
|
long m_pagesize;
|
||||||
|
#endif
|
||||||
|
std::map<char*, func_stub*> m_result;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -134,6 +134,7 @@ if(DOTEST)
|
||||||
include_directories(./src/service)
|
include_directories(./src/service)
|
||||||
include_directories(./src/tessocrutils)
|
include_directories(./src/tessocrutils)
|
||||||
include_directories(./src/view)
|
include_directories(./src/view)
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/3rdparty/stub_linux/)
|
||||||
#需要使用tesseract源码时添加tesseract三方库文件
|
#需要使用tesseract源码时添加tesseract三方库文件
|
||||||
# include_directories(/usr/include/leptonica)
|
# include_directories(/usr/include/leptonica)
|
||||||
# include_directories(${PROJECT_SOURCE_DIR}/3rdparty/tesseract_ocr/tesseract/include)
|
# include_directories(${PROJECT_SOURCE_DIR}/3rdparty/tesseract_ocr/tesseract/include)
|
||||||
|
@ -156,6 +157,7 @@ if(DOTEST)
|
||||||
aux_source_directory(src/view allTestSource)
|
aux_source_directory(src/view allTestSource)
|
||||||
aux_source_directory(tests allTestSource)
|
aux_source_directory(tests allTestSource)
|
||||||
aux_source_directory(tests/tessocrutils allTestSource)
|
aux_source_directory(tests/tessocrutils allTestSource)
|
||||||
|
aux_source_directory(${PROJECT_SOURCE_DIR}/3rdparty/stub_linux/ allTestSource)
|
||||||
#需要使用tesseract源码时添加tesseract三方库文件
|
#需要使用tesseract源码时添加tesseract三方库文件
|
||||||
# aux_source_directory(3rdparty/tesseract_ocr/tesseract/src/api allTestSource)
|
# aux_source_directory(3rdparty/tesseract_ocr/tesseract/src/api allTestSource)
|
||||||
# #aux_source_directory(3rdparty/tesseract_ocr/tesseract/src/arch allSource)
|
# #aux_source_directory(3rdparty/tesseract_ocr/tesseract/src/arch allSource)
|
||||||
|
|
|
@ -125,7 +125,7 @@ RecognitionResult TessOcrUtils::getRecogitionResult(const QString &imagePath,con
|
||||||
return t_result;
|
return t_result;
|
||||||
}
|
}
|
||||||
//获取识别结果
|
//获取识别结果
|
||||||
return getRecogitionResult(p_image,resultType);
|
return getRecognizeResult(p_image,resultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
//传入待识别图片的路径,获取纯字符串的识别结果
|
//传入待识别图片的路径,获取纯字符串的识别结果
|
||||||
|
@ -171,7 +171,7 @@ RecognitionResult TessOcrUtils::getRecogitionResult(QImage *image, const ResultT
|
||||||
//p_image->colormap->n;
|
//p_image->colormap->n;
|
||||||
p_image->data = reinterpret_cast<l_uint32*>(image->bits());
|
p_image->data = reinterpret_cast<l_uint32*>(image->bits());
|
||||||
//获取识别结果
|
//获取识别结果
|
||||||
return getRecogitionResult(p_image,resultType);
|
return getRecognizeResult(p_image,resultType);
|
||||||
}
|
}
|
||||||
|
|
||||||
//传入待识别图片,获取纯字符串的识别结果
|
//传入待识别图片,获取纯字符串的识别结果
|
||||||
|
@ -231,7 +231,7 @@ bool TessOcrUtils::setLanguagesPath(const QString langsPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取识别结果
|
//获取识别结果
|
||||||
RecognitionResult TessOcrUtils::getRecogitionResult(Pix * image,ResultType resultType)
|
RecognitionResult TessOcrUtils::getRecognizeResult(Pix * image,ResultType resultType)
|
||||||
{
|
{
|
||||||
QString errorMessage = "";
|
QString errorMessage = "";
|
||||||
ErrorCode errorCode = ErrorCode::UNKNOWN;
|
ErrorCode errorCode = ErrorCode::UNKNOWN;
|
||||||
|
|
|
@ -228,7 +228,7 @@ private :
|
||||||
* @param 返回的字符串结果类型
|
* @param 返回的字符串结果类型
|
||||||
* @return 返回识别结果
|
* @return 返回识别结果
|
||||||
*/
|
*/
|
||||||
RecognitionResult getRecogitionResult(Pix * image,ResultType resultType);
|
RecognitionResult getRecognizeResult(Pix * image,ResultType resultType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 设置返回结果,内部使用
|
* @brief 设置返回结果,内部使用
|
||||||
|
|
215
tests/tessocrutils/test_tessocrutils.cpp
Normal file
215
tests/tessocrutils/test_tessocrutils.cpp
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
* Copyright (C) 2019 ~ 2019 Deepin Technology Co., Ltd.
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
* Author: wangcong <wangcong@uniontech.com>
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
* Maintainer: wangcong <wangcong@uniontech.com>
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
|
||||||
|
* any later version.
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include "../../src/tessocrutils/tessocrutils.h"
|
||||||
|
#include "stub.h"
|
||||||
|
#include "addr_pri.h"
|
||||||
|
#include <QDir>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
class TessOcrUtilsTest:public testing::Test{
|
||||||
|
|
||||||
|
public:
|
||||||
|
Stub stub;
|
||||||
|
TessOcrUtils *m_tessOCrUtils = nullptr;
|
||||||
|
virtual void SetUp() override{
|
||||||
|
m_tessOCrUtils = TessOcrUtils::instance();
|
||||||
|
std::cout << "start TessOcrUtilsTest" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() override{
|
||||||
|
std::cout << "end TessOcrUtilsTest" << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ACCESS_PRIVATE_FUN(TessOcrUtils, bool(const QString), setLanguagesPath);
|
||||||
|
ACCESS_PRIVATE_FUN(TessOcrUtils, bool(ResultType), isExistsResultType);
|
||||||
|
ACCESS_PRIVATE_FUN(TessOcrUtils, QString(Languages), getLangStr);
|
||||||
|
ACCESS_PRIVATE_FUN(TessOcrUtils, Languages(), getSystemLang);
|
||||||
|
ACCESS_PRIVATE_FUN(TessOcrUtils, QString(), getLanguages);
|
||||||
|
ACCESS_PRIVATE_FUN(TessOcrUtils, RecognitionResult(Pix*, ResultType), getRecognizeResult);
|
||||||
|
ACCESS_PRIVATE_FUN(TessOcrUtils, void(ErrorCode, const QString,const ResultType,RecognitionResult &), setResult);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, tessOcrUtils)
|
||||||
|
{
|
||||||
|
EXPECT_NE(nullptr, m_tessOCrUtils);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, getRecogitionResultImagePathAndResultType)
|
||||||
|
{
|
||||||
|
//QString imagePath = "/media/wangcong/workspace/wangcong/workspace/qt_workspace/project/deepin-ocr/assets/testocr.png";
|
||||||
|
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
|
||||||
|
ResultType resultType = ResultType::RESULT_STRING;
|
||||||
|
RecognitionResult recognitionResult = m_tessOCrUtils->getRecogitionResult(imagePath,resultType);
|
||||||
|
EXPECT_EQ(true, recognitionResult.flag);
|
||||||
|
EXPECT_EQ("", recognitionResult.message);
|
||||||
|
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
|
||||||
|
EXPECT_EQ(resultType, recognitionResult.resultType);
|
||||||
|
//EXPECT_NE("", recognitionResult.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, getRecogitionResult2ImagePath)
|
||||||
|
{
|
||||||
|
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
|
||||||
|
RecognitionResult recognitionResult = m_tessOCrUtils->getRecogitionResult(imagePath);
|
||||||
|
recognitionResult = m_tessOCrUtils->getRecogitionResult(imagePath);
|
||||||
|
EXPECT_EQ(true, recognitionResult.flag);
|
||||||
|
EXPECT_EQ("", recognitionResult.message);
|
||||||
|
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
|
||||||
|
EXPECT_EQ(ResultType::RESULT_STRING, recognitionResult.resultType);
|
||||||
|
//EXPECT_NE("", recognitionResult.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, getRecogitionResultImageAndResultType)
|
||||||
|
{
|
||||||
|
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
|
||||||
|
ResultType resultType = ResultType::RESULT_STRING;
|
||||||
|
QImage* t_image = new QImage(imagePath);
|
||||||
|
RecognitionResult recognitionResult = TessOcrUtils::instance()->getRecogitionResult(t_image,resultType);
|
||||||
|
EXPECT_EQ(true, recognitionResult.flag);
|
||||||
|
EXPECT_EQ("", recognitionResult.message);
|
||||||
|
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
|
||||||
|
EXPECT_EQ(resultType, recognitionResult.resultType);
|
||||||
|
//EXPECT_NE("", recognitionResult.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, getRecogitionResultImage)
|
||||||
|
{
|
||||||
|
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
|
||||||
|
QImage* t_image = new QImage(imagePath);
|
||||||
|
RecognitionResult recognitionResult = TessOcrUtils::instance()->getRecogitionResult(t_image);
|
||||||
|
EXPECT_EQ(true, recognitionResult.flag);
|
||||||
|
EXPECT_EQ("", recognitionResult.message);
|
||||||
|
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
|
||||||
|
EXPECT_EQ(ResultType::RESULT_STRING, recognitionResult.resultType);
|
||||||
|
//EXPECT_NE("", recognitionResult.result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, isRunning)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(false, m_tessOCrUtils->isRunning());
|
||||||
|
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
|
||||||
|
ResultType resultType = ResultType::RESULT_STRING;
|
||||||
|
RecognitionResult recognitionResult = m_tessOCrUtils->getRecogitionResult(imagePath,resultType);
|
||||||
|
EXPECT_EQ(false, m_tessOCrUtils->isRunning());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, getRecognizeResult)
|
||||||
|
{
|
||||||
|
QString imagePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/Wallpapers/luca-micheli-ruWkmt3nU58-unsplash.jpg";
|
||||||
|
QImage* image = new QImage(imagePath);
|
||||||
|
ResultType resultType = ResultType::RESULT_STRING;
|
||||||
|
Pix *p_image;
|
||||||
|
p_image = pixCreate(image->width(), image->height(), image->depth());
|
||||||
|
p_image->w = static_cast<l_uint32>(image->width());
|
||||||
|
p_image->h = static_cast<l_uint32>(image->height());
|
||||||
|
p_image->d = static_cast<l_uint32>(image->depth());
|
||||||
|
p_image->spp = 3;
|
||||||
|
p_image->wpl = static_cast<l_uint32>(image->width());
|
||||||
|
p_image->refcount = 1;
|
||||||
|
p_image->xres = 0;
|
||||||
|
p_image->yres = 0;
|
||||||
|
p_image->informat = 0;
|
||||||
|
p_image->special = 0;
|
||||||
|
p_image->text = nullptr;
|
||||||
|
p_image->colormap = nullptr;
|
||||||
|
p_image->data = reinterpret_cast<l_uint32*>(image->bits());
|
||||||
|
RecognitionResult recognitionResult = call_private_fun::TessOcrUtilsgetRecognizeResult(*m_tessOCrUtils,p_image,resultType);
|
||||||
|
EXPECT_EQ(true, recognitionResult.flag);
|
||||||
|
EXPECT_EQ("", recognitionResult.message);
|
||||||
|
EXPECT_EQ(ErrorCode::OK, recognitionResult.errorCode);
|
||||||
|
EXPECT_EQ(ResultType::RESULT_STRING, recognitionResult.resultType);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, setLanguagesPath)
|
||||||
|
{
|
||||||
|
const QString TessDataPath = "/usr/share/deepin-ocr/tesslangs";
|
||||||
|
bool flag = call_private_fun::TessOcrUtilssetLanguagesPath(*m_tessOCrUtils,TessDataPath);
|
||||||
|
//EXPECT_EQ(true, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, isExistsResultType)
|
||||||
|
{
|
||||||
|
const QString TessDataPath = "/usr/share/deepin-ocr/tesslangs";
|
||||||
|
bool flag = call_private_fun::TessOcrUtilsisExistsResultType(*m_tessOCrUtils,ResultType::RESULT_STRING);
|
||||||
|
//EXPECT_EQ(true, flag);
|
||||||
|
flag = call_private_fun::TessOcrUtilsisExistsResultType(*m_tessOCrUtils,ResultType::RESULT_HTML);
|
||||||
|
//EXPECT_EQ(true, flag);
|
||||||
|
flag = call_private_fun::TessOcrUtilsisExistsResultType(*m_tessOCrUtils,ResultType::UNKNOWN_TYPE);
|
||||||
|
//EXPECT_EQ(false, flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, getLangStr)
|
||||||
|
{
|
||||||
|
QString lang = call_private_fun::TessOcrUtilsgetLangStr(*m_tessOCrUtils,Languages::ENG);
|
||||||
|
EXPECT_EQ("eng", lang);
|
||||||
|
lang = call_private_fun::TessOcrUtilsgetLangStr(*m_tessOCrUtils,Languages::CHI_SIM);
|
||||||
|
EXPECT_EQ("chi_sim", lang);
|
||||||
|
lang = call_private_fun::TessOcrUtilsgetLangStr(*m_tessOCrUtils,Languages::CHI_TRA);
|
||||||
|
EXPECT_EQ("chi_tra", lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, getSystemLang)
|
||||||
|
{
|
||||||
|
Languages lang = call_private_fun::TessOcrUtilsgetSystemLang(*m_tessOCrUtils);
|
||||||
|
EXPECT_NE(Languages::UNKNOWN_LAN, lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, getLanguages)
|
||||||
|
{
|
||||||
|
QString lang = call_private_fun::TessOcrUtilsgetLanguages(*m_tessOCrUtils);
|
||||||
|
EXPECT_NE("", lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(TessOcrUtilsTest, setResult)
|
||||||
|
{
|
||||||
|
RecognitionResult result ;
|
||||||
|
call_private_fun::TessOcrUtilssetResult(*m_tessOCrUtils,ErrorCode::UNKNOWN,"test",ResultType::RESULT_STRING,result);
|
||||||
|
EXPECT_EQ(false, result.flag);
|
||||||
|
EXPECT_EQ(ErrorCode::UNKNOWN, result.errorCode);
|
||||||
|
EXPECT_EQ("test", result.message);
|
||||||
|
EXPECT_EQ(ResultType::RESULT_STRING, result.resultType);
|
||||||
|
EXPECT_EQ("", result.result);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user