ARB
Group.cxx
Go to the documentation of this file.
1 // ============================================================= //
2 // //
3 // File : Group.cxx //
4 // Purpose : Handles for taxonomic groups //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in March 2017 //
7 // http://www.arb-home.de/ //
8 // //
9 // ============================================================= //
10 
11 #include "Group.hxx"
12 #include "GroupIterator.hxx"
13 
14 #include <AP_TreeSet.hxx>
15 
16 using namespace std;
17 
18 static AP_tree *find_node_with_groupdata(AP_tree *subtree, GBDATA *gb_group) {
19  // brute-force impl
20  // @@@ instead use group id (as stored in node) as hint to find group
21  if (subtree->is_leaf()) return NULp;
22  if (subtree->gb_node == gb_group) return subtree;
23 
24  AP_tree *found = find_node_with_groupdata(subtree->get_leftson(), gb_group);
25  if (!found) found = find_node_with_groupdata(subtree->get_rightson(), gb_group);
26  return found;
27 }
28 
29 bool Group::locate(AP_tree *subtree) const {
30  td_assert(is_valid());
31 
32  if (!is_located()) {
33  node = find_node_with_groupdata(subtree, gb_group);
34  td_assert(node); // wrong subtree specified!
35 
36  TreeNode *keeledToSon = node->keelTarget();
37  if (keeledToSon) {
38  node = DOWNCAST(AP_tree*, keeledToSon);
39  }
40  }
41 
42  td_assert(implicated(node, at_node(node)));
43  return node;
44 }
45 
46 // --------------------------------------------------------------------------------
47 
48 #ifdef UNIT_TESTS
49 #ifndef TEST_UNIT_H
50 #include <test_unit.h>
51 #endif
52 
53 void TEST_groups() {
54  GB_shell shell;
55  GBDATA *gb_main = GB_open("../../demo.arb", "r");
56 
57  SmartPtr<AP_tree_root> treeRoot = new AP_tree_root(new AliView(gb_main), NULp, false, NULp);
58 
59  {
60  GB_transaction ta(gb_main);
61  TEST_EXPECT_NO_ERROR(treeRoot->loadFromDB("tree_test"));
62  }
63 
64  AP_tree *rootNode = treeRoot->get_root_node();
65  AP_tree_set existingGroups;
66 
67  const int GROUP_COUNT = 8;
68 
69  collect_contained_groups(rootNode, existingGroups);
70  TEST_EXPECT_EQUAL(existingGroups.size(), GROUP_COUNT);
71 
72  {
73  Group gunknown;
74  TEST_EXPECT(!gunknown.is_valid());
75  TEST_EXPECT_NULL(gunknown.get_group_data());
76 
77  for (AP_tree_set_iter i = existingGroups.begin(); i != existingGroups.end(); ++i) {
78  AP_tree *node = *i;
79 
80  Group gfound(node);
81  Group gexisting(node->gb_node);
82 
83  TEST_EXPECT(gfound.is_located());
84  TEST_EXPECT(!gexisting.is_located());
85 
86  TEST_REJECT_NULL(gfound.get_group_data());
87  TEST_REJECT_NULL(gexisting.get_group_data());
88 
89  TEST_EXPECT(gexisting.locate(rootNode));
90  TEST_EXPECT(gexisting.is_located());
91  TEST_EXPECT_EQUAL(gfound.get_node(), gexisting.get_node());
92 
93  gexisting.dislocate();
94  TEST_EXPECT(!gexisting.is_located());
95 
96  // for all groupnodes test whether group 'gexisting' is at_node
97  int seen_exist = 0;
98  int seen_found = 0;
99  for (AP_tree_set_iter j = existingGroups.begin(); j != existingGroups.end(); ++j) {
100  AP_tree *testnode = *j;
101  if (gexisting.at_node(testnode)) seen_exist++;
102  if (gfound.at_node(testnode)) seen_found++;
103  }
104 
105  TEST_EXPECT_EQUAL(seen_found, 1);
106  TEST_EXPECT_EQUAL(seen_exist, 1);
107  TEST_EXPECT(gexisting.is_located());
108  TEST_EXPECT_EQUAL(gfound.get_node(), gexisting.get_node());
109 
110  { // compare node name
111  GB_transaction ta(gb_main);
112  TEST_EXPECT_EQUAL(gfound.get_name(), gfound.get_node()->name);
113  }
114  }
115  }
116 
117  // test GroupIterator
118  {
119  GroupIterator iter(rootNode);
120  GroupIterator reverse(rootNode, false);
121 
122  TEST_EXPECT(iter.valid());
123  TEST_EXPECT(reverse.valid());
124 
125  AP_tree *start = iter.node();
126  int count = 0;
127  int differed = 0;
128 
129  AP_tree *at = start;
130  do {
131  TEST_ANNOTATE(GBS_global_string("count=%i", count));
132 
133  AP_tree *rat = reverse.node();
134 
137 
138  fprintf(stderr, "iter=%s reverse=%s\n", at->name, rat->name);
139 
140  // Note: groupname 'outer' and 'test' are each used at two different groups!
141  // Counting leafs below ensures the iterator point to the right one of these duplicates!
142 
143  switch (count) {
144  case 0:
145  TEST_EXPECT_EQUAL(at->name, "outer"); TEST_EXPECT_EQUAL(at->count_leafs(), 15);
146  TEST_EXPECT_EQUAL(rat->name, "last");
147  TEST_EXPECT_EQUAL(iter.get_clade_level(), 1);
148  TEST_EXPECT_EQUAL(reverse.get_clade_level(), 1);
149  break;
150  case 2:
151  TEST_EXPECT_EQUAL(at->name, "test"); TEST_EXPECT_EQUAL(at->count_leafs(), 4);
152  TEST_EXPECT_EQUAL(rat->name, "inner");
153  TEST_EXPECT_EQUAL(iter.get_clade_level(), 2);
154  TEST_EXPECT_EQUAL(reverse.get_clade_level(), 2);
155  break;
156  case GROUP_COUNT-1:
157  TEST_EXPECT_EQUAL(at->name, "last");
158  TEST_EXPECT_EQUAL(rat->name, "outer"); TEST_EXPECT_EQUAL(rat->count_leafs(), 15);
159  TEST_EXPECT_EQUAL(iter.get_clade_level(), 1);
160  TEST_EXPECT_EQUAL(reverse.get_clade_level(), 1);
161  break;
162  }
163 
164  count++;
165  if (at != rat) ++differed;
166 
167  {
168  GroupIterator dup(iter);
169  TEST_EXPECT(dup.node() == iter.node());
170 
171  GroupIterator rdup(dup.next().node(), false);
172  TEST_EXPECT(dup.node() == rdup.node());
173 
174  dup.previous();
175  rdup.next();
176  TEST_EXPECT(dup.node() == iter.node());
177  TEST_EXPECT(dup.node() == rdup.node());
178 
179  dup.next();
180  rdup.previous();
181  TEST_EXPECT(dup.node() == rdup.node());
182  }
183 
184  at = iter.next().node();
185  reverse.next();
186  }
187  while (at != start);
188 
189  TEST_EXPECT_EQUAL(count, GROUP_COUNT);
190  TEST_EXPECT_EQUAL(differed, GROUP_COUNT%2 ? GROUP_COUNT-1 : GROUP_COUNT);
191  }
192 
193 
194 
195  GB_close(gb_main);
196 }
197 
198 #endif // UNIT_TESTS
199 
200 // --------------------------------------------------------------------------------
201 
GBDATA * get_group_data() const
Definition: Group.hxx:55
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
#define implicated(hypothesis, conclusion)
Definition: arb_assert.h:289
#define td_assert(cond)
Definition: Group.hxx:18
std::set< AP_tree * > AP_tree_set
Definition: AP_TreeSet.hxx:21
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
STL namespace.
bool is_valid() const
Definition: Group.hxx:48
#define DOWNCAST(totype, expr)
Definition: downcast.h:141
unsigned count_leafs() const
Definition: AP_Tree.cxx:840
static HelixNrInfo * start
#define TEST_EXPECT(cond)
Definition: test_unit.h:1313
Generic smart pointer.
Definition: smartptr.h:149
AP_tree_set::iterator AP_tree_set_iter
Definition: AP_TreeSet.hxx:22
#define TEST_REJECT_NULL(n)
Definition: test_unit.h:1310
GB_ERROR loadFromDB(const char *name) FINAL_OVERRIDE
Definition: AP_Tree.cxx:891
AP_tree_nlen * rootNode()
Definition: ap_main.hxx:54
bool locate(AP_tree *subtree) const
Definition: Group.cxx:29
bool is_leaf() const
Definition: TreeNode.h:171
#define TEST_EXPECT_NULL(n)
Definition: test_unit.h:1307
void collect_contained_groups(AP_tree *node, AP_tree_set &groups)
Definition: AP_TreeSet.cxx:36
char * name
Definition: TreeNode.h:134
#define TEST_EXPECT_NO_ERROR(call)
Definition: test_unit.h:1107
#define NULp
Definition: cxxforward.h:97
static AP_tree * find_node_with_groupdata(AP_tree *subtree, GBDATA *gb_group)
Definition: Group.cxx:18
GB_transaction ta(gb_var)
GBDATA * gb_node
Definition: TreeNode.h:133
GBDATA * gb_main
Definition: adname.cxx:33
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1283
bool is_normal_group() const
Definition: TreeNode.h:429
Definition: Group.hxx:20
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:649