From 7a5b6ca6fb71685660d3a8ac0f749e46893fa1ae Mon Sep 17 00:00:00 2001 From: zhengchao Date: Mon, 24 Sep 2018 11:23:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90gtest=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=E7=9A=84=E8=BF=81=E7=A7=BB=E3=80=82=E5=8E=9F?= =?UTF-8?q?maat=5Ftest.cpp=E6=94=B9=E4=B8=BAmaat=5Fdemo.cpp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 4 +- src/inc_internal/Maat_rule_internal.h | 2 +- test/CMakeLists.txt | 5 +- test/{maat_test.cpp => maat_demo.cpp} | 2 +- test/test_maatframe.cpp | 479 ++++++++++++++++++++------ 5 files changed, 378 insertions(+), 114 deletions(-) rename test/{maat_test.cpp => maat_demo.cpp} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 474ad43..3c60a47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,11 @@ -cmake_minimum_required (VERSION 2.6) +cmake_minimum_required (VERSION 3.5) project (maatframe) set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -Wall) include_directories(${PROJECT_SOURCE_DIR}/inc/) include_directories(/opt/MESA/include/MESA/) +enable_testing() + add_subdirectory (vendor) add_subdirectory (src) add_subdirectory (test) diff --git a/src/inc_internal/Maat_rule_internal.h b/src/inc_internal/Maat_rule_internal.h index 9585019..11e6ae9 100644 --- a/src/inc_internal/Maat_rule_internal.h +++ b/src/inc_internal/Maat_rule_internal.h @@ -356,7 +356,7 @@ struct _Maat_scanner_t MESA_lqueue_head region_update_q; void * expr_compiler; scan_result_t *region_rslt_buff; - MESA_lqueue_head tomb_ref;//reference of feather->garbage_q + MESA_lqueue_head tomb_ref;//reference of g_feather->garbage_q struct _region_stat_t region_counter[MAX_TABLE_NUM]; int max_thread_num; iconv_t iconv_handle[MAX_CHARSET_NUM][MAX_CHARSET_NUM];//iconv_handle[to][from] diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 00d5322..d2a8e69 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,5 @@ -add_executable(maat_test maat_test.cpp) -target_link_libraries(maat_test maat_frame_shared) +add_executable(maat_demo maat_demo.cpp) +target_link_libraries(maat_demo maat_frame_shared) add_executable(test_maatframe test_maatframe.cpp) target_link_libraries(test_maatframe maat_frame_shared gtest) @@ -11,3 +11,4 @@ file(COPY conf DESTINATION ./) file(COPY rule DESTINATION ./) file(COPY testdata DESTINATION ./) file(COPY testdata_uni2ascii DESTINATION ./) +add_test(NAME MaatframeFunctionTest COMMAND test_maatframe) \ No newline at end of file diff --git a/test/maat_test.cpp b/test/maat_demo.cpp similarity index 99% rename from test/maat_test.cpp rename to test/maat_demo.cpp index 0194467..b59bc78 100644 --- a/test/maat_test.cpp +++ b/test/maat_demo.cpp @@ -1062,7 +1062,7 @@ void maat_test_print_usage(void) printf("\t\t-r Read config redis %s:%u db0.\n",test_maat_redis_ip,test_maat_redis_port); printf("\tOption:\n"); printf("\t\t-d Deferred Loading config.\n"); - printf("example: ./maat_test -j -d\n"); + printf("example: ./maat_demo -j -d\n"); return; } diff --git a/test/test_maatframe.cpp b/test/test_maatframe.cpp index 6edca83..ea49a8c 100644 --- a/test/test_maatframe.cpp +++ b/test/test_maatframe.cpp @@ -30,8 +30,12 @@ extern int my_scandir(const char *dir, struct dirent ***namelist, int(*compar)(const void *, const void *)); -Maat_feather_t feather=NULL; +Maat_feather_t g_feather=NULL; void *logger=NULL; +int g_iThreadNum=4; +const char* table_info_path="./table_info.conf"; +int scan_interval_ms=1; +int effective_interval_ms=0; void Maat_read_entry_start_cb(int update_type,void* u_para) { @@ -94,11 +98,11 @@ void test_plugin_table(Maat_feather_t feather,const char* table_name, TEST(PluginTable, Callback) { - test_plugin_table(feather, "QD_ENTRY_INFO", + test_plugin_table(g_feather, "QD_ENTRY_INFO", Maat_read_entry_start_cb, Maat_read_entry_cb, Maat_read_entry_finish_cb, - feather, + g_feather, logger); } @@ -111,10 +115,10 @@ TEST(StringScan, Full) const char* table_name="HTTP_URL"; scan_status_t mid=NULL; const char* scan_data="http://www.cyberessays.com/search_results.php?action=search&query=yulingjing,abckkk,1234567"; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); - ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + ret=Maat_full_scan_string(g_feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), result,found_pos, 4, &mid, 0); EXPECT_GE(ret, 1); @@ -137,18 +141,18 @@ TEST(IPScan, IPv4) ipv4_addr.v4=&v4_addr; const char* scan_data="http://www.cyberessays.com/search_results.php?action=search&query=yulingjing,abckkk,1234567"; - table_id=Maat_table_register(feather,"HTTP_URL"); + table_id=Maat_table_register(g_feather,"HTTP_URL"); ASSERT_GT(table_id, 0); - ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + ret=Maat_full_scan_string(g_feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), result,NULL, 4, &mid, 0); EXPECT_GE(ret, 1); - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); EXPECT_GT(table_id, 0); - ret=Maat_scan_proto_addr(feather,table_id,&ipv4_addr,6,result,4, &mid,0); + ret=Maat_scan_proto_addr(g_feather,table_id,&ipv4_addr,6,result,4, &mid,0); EXPECT_GT(ret, 0); Maat_clean_status(&mid); @@ -170,12 +174,12 @@ TEST(IPScan, IPv6) v6_addr.dest=htons(80); ipv6_addr.v6=&v6_addr; const char* table_name="IP_CONFIG"; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); EXPECT_GT(table_id, 0); //for improving performance. - Maat_set_scan_status(feather, &mid, MAAT_SET_SCAN_LAST_REGION,NULL, 0); - ret=Maat_scan_proto_addr(feather,table_id,&ipv6_addr,6,result,4, &mid,0); + Maat_set_scan_status(g_feather, &mid, MAAT_SET_SCAN_LAST_REGION,NULL, 0); + ret=Maat_scan_proto_addr(g_feather,table_id,&ipv6_addr,6,result,4, &mid,0); EXPECT_EQ(ret, -2); Maat_clean_status(&mid); return; @@ -188,10 +192,10 @@ TEST(IntervalScan, Pure) struct Maat_rule_t result[4]; const char* table_name="CONTENT_SIZE"; scan_status_t mid=NULL; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); - ret=Maat_scan_intval(feather, table_id, scan_val, result,4, &mid, 0); + ret=Maat_scan_intval(g_feather, table_id, scan_val, result,4, &mid, 0); EXPECT_EQ(ret, -2); Maat_clean_status(&mid); return; @@ -207,7 +211,7 @@ TEST(DigestScan, Pure) struct Maat_rule_t result[4]; stream_para_t sp=NULL; scan_status_t mid=NULL; - table_id=Maat_table_register(feather, table_name); + table_id=Maat_table_register(g_feather, table_name); ASSERT_GT(table_id, 0); ret=stat(file_name,&digest_fstat); @@ -216,7 +220,7 @@ TEST(DigestScan, Pure) FILE* fp=fopen(file_name,"r"); ASSERT_FALSE(fp==NULL); - sp=Maat_stream_scan_digest_start(feather, table_id, digest_fstat.st_size, 0); + sp=Maat_stream_scan_digest_start(g_feather, table_id, digest_fstat.st_size, 0); while(0==feof(fp)) { read_size=fread(digest_test_buff,1,sizeof(digest_test_buff),fp); @@ -245,16 +249,16 @@ TEST(StringScan, EncodedURL) const char* table_name="HTTP_URL"; scan_status_t mid=NULL; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); - ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, url_utf8, strlen(url_utf8), + ret=Maat_full_scan_string(g_feather, table_id,CHARSET_GBK, url_utf8, strlen(url_utf8), result,found_pos, 4, &mid, 0); EXPECT_GE(ret, 1); Maat_clean_status(&mid); - ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, url_gb2312, strlen(url_gb2312), + ret=Maat_full_scan_string(g_feather, table_id,CHARSET_GBK, url_gb2312, strlen(url_gb2312), result,found_pos, 4, &mid, 0); EXPECT_GE(ret, 1); @@ -276,7 +280,7 @@ TEST(StringScan, UnicodeEscape) const char* table_name="KEYWORDS_TABLE"; scan_status_t mid=NULL; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); n = my_scandir(test_data_dir, &namelist, NULL, (int (*)(const void*, const void*))alphasort); @@ -296,7 +300,7 @@ TEST(StringScan, UnicodeEscape) printf("fopen %s error.\n",file_path);; continue; } - sp=Maat_stream_scan_string_start(feather,table_id,0); + sp=Maat_stream_scan_string_start(g_feather,table_id,0); ASSERT_FALSE(sp==NULL); read_len=fread(buff,1,sizeof(buff),fp); @@ -333,10 +337,10 @@ TEST(StringScan, MaatUnescape) const char* table_name="KEYWORDS_TABLE"; scan_status_t mid=NULL; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); - ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + ret=Maat_full_scan_string(g_feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), result, NULL, 4, &mid, 0); EXPECT_EQ(ret, 1); @@ -353,11 +357,11 @@ TEST(StringScan, StreamInput) const char* table_name="HTTP_URL"; scan_status_t mid=NULL; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); struct Maat_hit_detail_t *hit_detail=(struct Maat_hit_detail_t *)malloc(sizeof(struct Maat_hit_detail_t)*10); - stream_para_t sp=Maat_stream_scan_string_start(feather,table_id,0); + stream_para_t sp=Maat_stream_scan_string_start(g_feather,table_id,0); ASSERT_FALSE(sp==NULL); int detail_ret=0; @@ -384,11 +388,11 @@ TEST(SimilarScan, Pure) const char* table_name="SIM_URL"; scan_status_t mid=NULL; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); - ret=Maat_similar_scan_string(feather, table_id, scan_data, strlen(scan_data), + ret=Maat_similar_scan_string(g_feather, table_id, scan_data, strlen(scan_data), result, 4, &mid, 0); EXPECT_EQ(ret, 1); @@ -406,13 +410,13 @@ TEST(TableInfo, Conjunction) const char* table_name="HTTP_URL", *conj_table_name="HTTP_HOST"; scan_status_t mid=NULL; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); - conj_table_id=Maat_table_register(feather,conj_table_name); + conj_table_id=Maat_table_register(g_feather,conj_table_name); ASSERT_EQ(conj_table_id, table_id); - ret=Maat_full_scan_string(feather, conj_table_id,CHARSET_GBK, scan_data, strlen(scan_data), + ret=Maat_full_scan_string(g_feather, conj_table_id,CHARSET_GBK, scan_data, strlen(scan_data), result,found_pos, 4, &mid, 0); EXPECT_EQ(ret, 2); @@ -435,12 +439,12 @@ void test_offset_str_scan_with_chunk(int chunk_size) ASSERT_FALSE(fp==NULL); char scan_data[chunk_size]; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); struct Maat_hit_detail_t *hit_detail=(struct Maat_hit_detail_t *)malloc(sizeof(struct Maat_hit_detail_t)*10); - stream_para_t sp=Maat_stream_scan_string_start(feather,table_id,0); + stream_para_t sp=Maat_stream_scan_string_start(g_feather,table_id,0); int detail_ret=0; ASSERT_FALSE(sp==NULL); @@ -494,10 +498,10 @@ TEST(RuleTags, Plugin) { int table_id=0,ret=0; const char* table_name="TEST_EFFECTIVE_RANGE_TABLE"; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); - ret=Maat_table_callback_register(feather, table_id, + ret=Maat_table_callback_register(g_feather, table_id, NULL, accept_tags_entry_cb, NULL, @@ -516,16 +520,16 @@ TEST(RuleTags, Compile) const char* should_hit="string bbb should hit"; const char* should_not_hit="string aaa should not hit"; const char* table_name="HTTP_URL"; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); - ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, should_not_hit, strlen(should_not_hit), + ret=Maat_full_scan_string(g_feather, table_id,CHARSET_GBK, should_not_hit, strlen(should_not_hit), result,NULL, 4, &mid, 0); EXPECT_LE(ret, 0); - ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, should_hit, strlen(should_hit), + ret=Maat_full_scan_string(g_feather, table_id,CHARSET_GBK, should_hit, strlen(should_hit), result,NULL, 4, &mid, 0); EXPECT_EQ(ret, 1); @@ -605,7 +609,6 @@ TEST(StreamFuzzyHash, Pure) SFH_release(fhandle); EXPECT_STREQ(sfh_ordered, sfh_unorder); -error_out: fclose(fp); free(file_buff); free(sfh_ordered); @@ -623,10 +626,10 @@ TEST(ScanResult, LongerServiceDefine) const char* scan_data="soq is using table conjunction function.http://www.3300av.com/novel/27122.txt"; const char* table_name="HTTP_URL"; - table_id=Maat_table_register(feather,table_name); + table_id=Maat_table_register(g_feather,table_name); ASSERT_GT(table_id, 0); - ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + ret=Maat_full_scan_string(g_feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), result, NULL, 4, &mid, 0); EXPECT_EQ(ret, 2); @@ -634,102 +637,360 @@ TEST(ScanResult, LongerServiceDefine) EXPECT_GT(result[1].serv_def_len, 128); char* buff=(char*)malloc(sizeof(char)*result[1].serv_def_len); - ret=Maat_read_rule(feather, result+1, MAAT_RULE_SERV_DEFINE, buff, result[1].serv_def_len); + ret=Maat_read_rule(g_feather, result+1, MAAT_RULE_SERV_DEFINE, buff, result[1].serv_def_len); EXPECT_EQ(ret, result[1].serv_def_len); Maat_clean_status(&mid); free(buff); return; } - -void maat_test_print_usage(void) +class MaatCmdTest : public testing::Test { - printf("Maat Test Usage:\n"); - printf("\tSource:\n"); - printf("\t\t-j Test updating from %s. https://www.sojson.com/yasuo.html\n",json_path); - printf("\t\t-u Load config from %s, and monitor %s. Need manually move inc index.\n",ful_cfg_dir,inc_cfg_dir); - printf("\t\t-r Read config redis %s:%u db0.\n",test_maat_redis_ip,test_maat_redis_port); - printf("\tOption:\n"); - printf("\t\t-d Deferred Loading config.\n"); - printf("example: ./maat_test -j -d\n"); + +protected: + static void SetUpTestCase() + { + void *logger=NULL; + logger=MESA_create_runtime_log_handle("test_maat_redis.log",0); + + _shared_feather=Maat_feather(g_iThreadNum, table_info_path, logger); + Maat_set_feather_opt(_shared_feather,MAAT_OPT_INSTANCE_NAME,"redis", strlen("redis")+1); + Maat_set_feather_opt(_shared_feather, MAAT_OPT_REDIS_IP, test_maat_redis_ip, strlen(test_maat_redis_ip)+1); + Maat_set_feather_opt(_shared_feather, MAAT_OPT_REDIS_PORT, &test_maat_redis_port, sizeof(test_maat_redis_port)); + Maat_set_feather_opt(_shared_feather, MAAT_OPT_SCANDIR_INTERVAL_MS,&scan_interval_ms, sizeof(scan_interval_ms)); + //Set a short intevral for testing. + Maat_set_feather_opt(_shared_feather, MAAT_OPT_EFFECT_INVERVAL_MS,&effective_interval_ms, sizeof(effective_interval_ms)); + Maat_initiate_feather(_shared_feather); + Maat_cmd_flushDB(_shared_feather); + } + static void TearDownTestCase() + { + Maat_burn_feather(_shared_feather); + + } + // Some expensive resource shared by all tests. + static Maat_feather_t _shared_feather; +}; +Maat_feather_t MaatCmdTest::_shared_feather; + +int test_add_expr_command(Maat_feather_t feather,const char* region_table,int config_id, int timeout,int label_id, const char* keywords) +{ + struct Maat_cmd_t* cmd=NULL; + struct Maat_rule_t rule; + char huge_serv_def[1024*2]; + memset(huge_serv_def,'s',sizeof(huge_serv_def)); + struct Maat_region_t region; + int group_num=1,ret=0; + memset(&rule,0,sizeof(rule)); + rule.config_id=config_id; + + strcpy(rule.service_defined,"maat_command"); + //MUST acqire by function, because Maat_cmd_t has some hidden members. + cmd=Maat_create_cmd(&rule, group_num); + cmd->expire_after=timeout; + cmd->label_id=label_id; + memset(®ion,0,sizeof(region)); + region.region_type=REGION_EXPR; + region.table_name=region_table; + region.expr_rule.district=NULL; + region.expr_rule.keywords=keywords; + region.expr_rule.expr_type=EXPR_TYPE_AND; + region.expr_rule.match_method=MATCH_METHOD_SUB; + region.expr_rule.hex_bin=UNCASE_PLAIN; + Maat_cmd_set_opt(cmd, MAAT_RULE_SERV_DEFINE, huge_serv_def, sizeof(huge_serv_def)); + Maat_add_region2cmd(cmd, 0, ®ion); + //use pipeline model. + ret=Maat_cmd_append(feather, cmd, MAAT_OP_ADD); + if(ret<0) + { + printf("Add Maat command %d failed.\n",rule.config_id); + Maat_free_cmd(cmd); + return 0; + } + //cmd has been saved in feather, so free cmd before commit is allowed. + Maat_free_cmd(cmd); + ret=Maat_cmd_commit(feather); + if(ret<0) + { + printf("Commit Maat command %d failed.\n",rule.config_id); + } + return 0; + +} +int del_command(Maat_feather_t feather,int config_id) +{ + struct Maat_cmd_t* cmd=NULL; + struct Maat_rule_t rule; + int ret=0; + memset(&rule,0,sizeof(rule)); + rule.config_id=config_id; + cmd=Maat_create_cmd(&rule, 0); + ret=Maat_cmd(feather, cmd, MAAT_OP_DEL); + if(ret<0) + { + printf("Delete Maat command %d failed.\n",rule.config_id); + } + Maat_free_cmd(cmd); + return 0; +} + +TEST_F(MaatCmdTest, Expr) +{ + const char* scan_data="Hiredis is a minimalistic C client library for the Redis database.\r\n"; + const char* table_name="HTTP_URL"; + + const char* keywords1="Hiredis"; + const char* keywords2="C Client"; + char escape_buff1[256],escape_buff2[256]; + char keywords[256]; + scan_status_t mid=NULL; + int config_id=-1, table_id=0, ret=0; + int output_ids[4]; + int output_id_cnt=0; + struct Maat_rule_t result; + int timeout=0;//seconds + int label_id=5210; + long long version_before=0,version_after=0; + Maat_feather_t feather=MaatCmdTest::_shared_feather; + + Maat_str_escape(escape_buff1, sizeof(escape_buff1),keywords1); + Maat_str_escape(escape_buff2, sizeof(escape_buff2),keywords2); + snprintf(keywords,sizeof(keywords),"%s&%s",escape_buff1,escape_buff2); + config_id=(int)Maat_cmd_incrby(feather, "TEST_SEQ", 1); + + ret=Maat_read_state(feather,MAAT_STATE_VERSION, &version_before, sizeof(version_before)); + test_add_expr_command(feather,table_name,config_id, 0, label_id, keywords); + usleep(WAIT_FOR_EFFECTIVE_US);//waiting for commands go into effect + + ret=Maat_read_state(feather,MAAT_STATE_VERSION, &version_after, sizeof(version_after)); + EXPECT_EQ(ret, 0); + table_id=Maat_table_register(feather,table_name); + ASSERT_GT(table_id, 0); + ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + &result,NULL, 1, + &mid, 0); + EXPECT_GT(ret, 0); + EXPECT_EQ(result.config_id, config_id); + + Maat_clean_status(&mid); + output_id_cnt=Maat_cmd_select(feather,label_id, output_ids, 4); + EXPECT_EQ(output_id_cnt, 1); + EXPECT_EQ(output_ids[0], config_id); + + + del_command(feather, config_id); + usleep(WAIT_FOR_EFFECTIVE_US);//waiting for commands go into effect + ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + &result,NULL, 1, + &mid, 0); + EXPECT_EQ(ret, 0); + Maat_clean_status(&mid); + + timeout=1; + config_id=(int)Maat_cmd_incrby(feather, "TEST_SEQ", 1); + test_add_expr_command(feather,table_name,config_id, timeout, label_id, keywords); + usleep(timeout*1000*1000+WAIT_FOR_EFFECTIVE_US); + ret=Maat_full_scan_string(feather, table_id,CHARSET_GBK, scan_data, strlen(scan_data), + &result,NULL, 1, + &mid, 0); + EXPECT_EQ(ret, 0); +} +TEST_F(MaatCmdTest, Lines) +{ + const int TEST_CMD_LINE_NUM=4; + const struct Maat_line_t *p_line[TEST_CMD_LINE_NUM]; + struct Maat_line_t line_rule[TEST_CMD_LINE_NUM]; + char table_line[TEST_CMD_LINE_NUM][128]; + int ret=0,i=0; + Maat_feather_t feather=MaatCmdTest::_shared_feather; + memset(&line_rule,0,sizeof(line_rule)); + for(i=0;i