1 #include <muleunit/test.h>
2 
3 #include <wx/filename.h>
4 #include <MemFile.h>
5 #include <tags/FileTags.h>
6 #include <math.h>
7 
8 #include "MD4Hash.h"
9 #include "amule.h"
10 #include "Packet.h"
11 #include <vector>
12 
13 using namespace muleunit;
14 
15 DECLARE_SIMPLE(CTag)
16 
17 void test_taglist_serialization(TagPtrList & taglist, byte* packet, uint64 packet_len);
18 
19 template <class T1, class T2>
AssertEquals(const T1 & a,const T2 & b)20 void AssertEquals(const T1& a, const T2& b)
21 {
22 	ASSERT_EQUALS(a, b);
23 }
24 
25 struct BLOBValue : std::vector<byte>
26 {
BLOBValueBLOBValue27 	BLOBValue(uint32 _length, const byte* _ptr)
28 		: std::vector<byte > (_ptr, _ptr + _length)
29 	{}
30 };
31 
32 struct BSOBValue : std::vector<byte>
33 {
BSOBValueBSOBValue34 	BSOBValue(uint8 _length, const byte* _ptr)
35 		: std::vector<byte > (_ptr, _ptr + _length)
36 	{}
37 };
38 
valid_tag_value(const BLOBValue & x)39 BLOBValue valid_tag_value(const BLOBValue& x)	{ return x; }
valid_tag_value(const BSOBValue & x)40 BSOBValue valid_tag_value(const BSOBValue& x)	{ return x; }
valid_tag_value(const CMD4Hash & x)41 CMD4Hash valid_tag_value(const CMD4Hash& x)	{ return x; }
valid_tag_value(float x)42 float valid_tag_value(float x)			{ return x; }
valid_tag_value(const wxString & x)43 wxString valid_tag_value(const wxString& x)	{ return x; }
valid_tag_value(int x)44 uint64 valid_tag_value(int x)			{ return x; }
valid_tag_value(long long x)45 uint64 valid_tag_value(long long x)		{ return x; }
valid_tag_value(uint64 x)46 uint64 valid_tag_value(uint64 x)		{ return x; }
47 
48 template<class T>
toString(const T & value)49 wxString toString(const T& value)
50 {
51 	wxString buf;
52 
53 	return buf << value;
54 }
55 
56 template<class T>
toString(T & value)57 wxString toString(T& value)
58 {
59 	wxString buf;
60 
61 	return buf << value;
62 }
63 
64 template<>
toString(const CMD4Hash & value)65 wxString toString(const CMD4Hash& value)
66 {
67 	return value.Encode();
68 }
69 
70 template<>
toString(CMemFile & buf)71 wxString toString(CMemFile& buf)
72 {
73 	uint64 curpos = buf.GetPosition();
74 	wxString result;
75 	buf.Seek(0, wxFromStart);
76 	for (uint64 i = 0; i < buf.GetLength(); i++) {
77 		result += wxString::Format(wxT("0x%02x,"), buf.ReadUInt8());
78 	}
79 	buf.Seek(curpos, wxFromStart);
80 
81 	return result;
82 }
83 
84 template<>
toString(const BSOBValue & buf)85 wxString toString(const BSOBValue& buf)
86 {
87 	wxString result;
88 	for (uint64 i = 0; i < buf.size(); i++) {
89 		result += wxString::Format(wxT("0x%02x,"), buf[i]);
90 	}
91 	return result;
92 }
93 
94 template<>
toString(const BLOBValue & buf)95 wxString toString(const BLOBValue& buf)
96 {
97 	wxString result;
98 	for (uint64 i = 0; i < buf.size(); i++) {
99 		result += wxString::Format(wxT("0x%02x,"), buf[i]);
100 	}
101 	return result;
102 }
103 
104 template<>
AssertEquals(const CMD4Hash & a,const CMD4Hash & b)105 void AssertEquals(const CMD4Hash& a, const CMD4Hash& b)
106 {
107 	CONTEXT(wxT("Compare CMD4Hashes"));
108 	ASSERT_EQUALS(a.Encode(), b.Encode());
109 }
110 
111 template<>
AssertEquals(const BSOBValue & a,const BSOBValue & b)112 void AssertEquals(const BSOBValue& a, const BSOBValue& b)
113 {
114 	CONTEXT(wxT("Compare BSOBValue"));
115 	ASSERT_EQUALS(toString(a), toString(b));
116 }
117 
118 template<>
AssertEquals(const BLOBValue & a,const BLOBValue & b)119 void AssertEquals(const BLOBValue& a, const BLOBValue& b)
120 {
121 	CONTEXT(wxT("Compare BLOBValue"));
122 	ASSERT_EQUALS(toString(a), toString(b));
123 }
124 
CheckTagName(const wxString & tagName,CTag * tag)125 void CheckTagName(const wxString& tagName, CTag* tag)
126 {
127 	CONTEXT(wxT("Checking string tagname"));
128 	ASSERT_EQUALS(tagName, tag->GetName());
129 }
130 
CheckTagName(uint8 tagName,CTag * tag)131 void CheckTagName(uint8 tagName, CTag* tag)
132 {
133 	CONTEXT(wxT("Checking int tagname"));
134 	ASSERT_EQUALS(tagName, tag->GetNameID());
135 }
136 
137 
138 typedef bool (CTag::*CTagTypeChecker)() const;
139 
140 template<class T>
141 struct CTagAccess {};
142 
143 template<>
144 struct CTagAccess<wxString>
145 {
IsRightTypeCTagAccess146 	static bool IsRightType(CTag* tag)
147 	{
148 		return tag->IsStr();
149 	}
150 
GetValueCTagAccess151 	static const wxString & GetValue(CTag* tag)
152 	{
153 		return tag->GetStr();
154 	}
155 };
156 
157 template<>
158 struct CTagAccess<CMD4Hash>
159 {
IsRightTypeCTagAccess160 	static bool IsRightType(CTag* tag)
161 	{
162 		return tag->IsHash();
163 	}
164 
GetValueCTagAccess165 	static const CMD4Hash & GetValue(CTag* tag)
166 	{
167 		return tag->GetHash();
168 	}
169 };
170 
171 template<>
172 struct CTagAccess<float>
173 {
IsRightTypeCTagAccess174 	static bool IsRightType(CTag* tag)
175 	{
176 		return tag->IsFloat();
177 	}
178 
GetValueCTagAccess179 	static float GetValue(CTag* tag)
180 	{
181 		return tag->GetFloat();
182 	}
183 };
184 
185 template<>
186 struct CTagAccess<uint64>
187 {
IsRightTypeCTagAccess188 	static bool IsRightType(CTag* tag)
189 	{
190 		return tag->IsInt();
191 	}
192 
GetValueCTagAccess193 	static uint64 GetValue(CTag* tag)
194 	{
195 		return tag->GetInt();
196 	}
197 };
198 
199 template<>
200 struct CTagAccess<BLOBValue>
201 {
IsRightTypeCTagAccess202 	static bool IsRightType(CTag* tag)
203 	{
204 		return tag->IsBlob();
205 	}
206 
GetValueCTagAccess207 	static BLOBValue GetValue(CTag* tag)
208 	{
209 		return BLOBValue(tag->GetBlobSize(), tag->GetBlob());
210 	}
211 };
212 
213 template<>
214 struct CTagAccess<BSOBValue>
215 {
IsRightTypeCTagAccess216 	static bool IsRightType(CTag* tag)
217 	{
218 		return tag->IsBsob();
219 	}
220 
GetValueCTagAccess221 	static BSOBValue GetValue(CTag* tag) {
222 		return BSOBValue(tag->GetBsobSize(), tag->GetBsob());
223 	}
224 };
225 
226 template<class V>
CheckTagValue(V tagValue,CTag * tag)227 void CheckTagValue(V tagValue, CTag* tag)
228 {
229 	CONTEXT(wxT("Check tag value"));
230 
231 	AssertEquals(tagValue, CTagAccess< V >::GetValue(tag));
232 }
233 
234 template<class V>
CheckTagType(V,CTag * tag)235 void CheckTagType(V, CTag* tag)
236 {
237 	CONTEXT(wxT("Check tag type"));
238 	ASSERT_EQUALS(true, CTagAccess<V>::IsRightType(tag));
239 }
240 
241 template<class V, class TName>
CheckTagData(CTag * tag,TName tagName,const V & tagValue)242 void CheckTagData(CTag* tag, TName tagName, const V& tagValue)
243 {
244 	CONTEXT(wxT("Expected tag value:") + toString(tagValue));
245 	CONTEXT(wxT("Parsed tag info:") + tag->GetFullInfo());
246 
247 	CheckTagType(tagValue, tag);
248 	CheckTagName(tagName, tag);
249 	CheckTagValue(valid_tag_value(tagValue), tag);
250 }
251 
test_taglist_serialization(TagPtrList & taglist,byte * packet,uint64 packet_len)252 void test_taglist_serialization(TagPtrList& taglist, byte* packet, uint64 packet_len)
253 {
254 	CMemFile fout;
255 
256 	{
257 		CONTEXT(wxT("Writing taglist to CMemFile"));
258 
259 		fout.WriteTagPtrList(taglist);
260 	}
261 
262 	// Rewind file
263 	fout.Seek(0, wxFromStart);
264 
265 	{
266 		CONTEXT(wxT("Check taglist serialization length"));
267 		ASSERT_EQUALS(packet_len, fout.GetLength());
268 	}
269 
270 	std::vector<byte> buf(packet_len);
271 
272 	{
273 		CONTEXT(wxT("Reading back serialized taglist bytes from CMemFile"));
274 		fout.Read(&buf[0], packet_len);
275 	}
276 
277 	for (uint64 i = 0; i < packet_len; i++) {
278 		CONTEXT(wxString::Format(wxT("Comparing serialized byte #%") wxLongLongFmtSpec wxT("u"), i));
279 
280 		ASSERT_EQUALS(packet[i], buf[i]);
281 	}
282 }
283 
ReadTagPtrList(TagPtrList & taglist,byte * packet,uint64 packet_len)284 void ReadTagPtrList(TagPtrList& taglist, byte* packet, uint64 packet_len)
285 {
286 
287 	CONTEXT(wxT("Reading taglist from buffer"));
288 	CMemFile fin(packet, packet_len);
289 	fin.ReadTagPtrList(&taglist, true);
290 
291 	{
292 		CONTEXT(wxT("Verify position is at end of packet"));
293 		ASSERT_EQUALS(packet_len, fin.GetPosition());
294 	}
295 }
296 
297 TEST_M(CTag, ReadTagList1, wxT("Kad: Parse taglist from Kad packet with UTF8 string #1"))
298 {
299 	byte packet[] = {
300 		0x07,
301 		/*Tag1*/ 0x02, 0x01, 0x00, 0x01, 0x22, 0x00, 0x47, 0x65, 0x6d, 0x20, 0x42, 0x6f, 0x79, 0x20, 0x2d,
302 		0x20, 0x53, 0x61, 0x72, 0xc3, 0xa0, 0x20, 0x70, 0x65, 0x72, 0x63, 0x68, 0xc3, 0xa8, 0x20, 0x74,
303 		0x69, 0x20, 0x61, 0x6d, 0x6f, 0x2e, 0x6d, 0x70, 0x33,
304 		/*Tag2*/ 0x03, 0x01, 0x00, 0x02, 0x1d, 0x6f, 0x1f, 0x00,
305 		/*Tag3*/ 0x09, 0x01, 0x00, 0x15, 0x01,
306 		/*Tag4*/ 0x02, 0x01, 0x00, 0x03, 0x05, 0x00, 0x41, 0x75, 0x64, 0x69, 0x6f,
307 		/*Tag5*/ 0x09, 0x01, 0x00, 0xd3, 0x6b,
308 		/*Tag6*/ 0x09, 0x01, 0x00, 0xd4, 0x9a,
309 		/*Tag7*/ 0x03, 0x01, 0x00, 0x33, 0x2f, 0x00, 0x01, 0x01
310 	};
311 
312 	TagPtrList taglist;
313 	ReadTagPtrList(taglist, packet, sizeof (packet));
314 	TagPtrList::iterator it = taglist.begin();
315 
316 	CheckTagData(*it++, TAG_FILENAME, valid_tag_value(wxT("Gem Boy - Sarà perchè ti amo.mp3")));
317 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(2060061));
318 	CheckTagData(*it++, TAG_SOURCES, valid_tag_value(1));
319 	CheckTagData(*it++, TAG_FILETYPE, valid_tag_value(ED2KFTSTR_AUDIO));
320 	CheckTagData(*it++, TAG_MEDIA_LENGTH, valid_tag_value(107));
321 	CheckTagData(*it++, TAG_MEDIA_BITRATE, valid_tag_value(154));
322 	CheckTagData(*it++, TAG_PUBLISHINFO, valid_tag_value(16842799));
323 
324 	ASSERT_TRUE(it == taglist.end());
325 	test_taglist_serialization(taglist, packet, sizeof (packet));
326 	deleteTagPtrListEntries(&taglist);
327 }
328 
329 TEST_M(CTag, ReadTagList2, wxT("Kad: Parse taglist from Kad packet with UTF8 string #2"))
330 {
331 	byte packet[] = {
332 		0x05,
333 		/*Tag1*/0x02, 0x01, 0x00, 0x01, 0x33, 0x00, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61,
334 		0x74, 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x31,
335 		0x38, 0x39, 0x33, 0x2d, 0xe2, 0x82, 0xac, 0xe2, 0x82, 0xac, 0xc3, 0xa8, 0xc3, 0xa9, 0xc3, 0xa7,
336 		0xc3, 0xa0, 0xc3, 0xb9, 0xc2, 0xa7, 0x2e, 0x74, 0x78, 0x74,
337 		/*Tag2*/0x09, 0x01, 0x00, 0x02, 0x0d,
338 		/*Tag3*/0x09, 0x01, 0x00, 0x15, 0x00,
339 		/*Tag4*/0x02, 0x01, 0x00, 0x03, 0x03, 0x00, 0x44, 0x6f, 0x63, 0x03, 0x01, 0x00,
340 		0x33, 0xe8, 0x03, 0x01, 0x01
341 	};
342 
343 	TagPtrList taglist;
344 	ReadTagPtrList(taglist, packet, sizeof (packet));
345 	TagPtrList::iterator it = taglist.begin();
346 
347 	CheckTagData(*it++, TAG_FILENAME, valid_tag_value(wxT("Serialization Test File 1893-€€èéçàù§.txt")));
348 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(13));
349 	CheckTagData(*it++, TAG_SOURCES, valid_tag_value(0));
350 	CheckTagData(*it++, TAG_FILETYPE, valid_tag_value(ED2KFTSTR_DOCUMENT));
351 	CheckTagData(*it++, TAG_PUBLISHINFO, valid_tag_value(16843752));
352 
353 	ASSERT_TRUE(it == taglist.end());
354 	test_taglist_serialization(taglist, packet, sizeof (packet));
355 	deleteTagPtrListEntries(&taglist);
356 
357 }
358 
359 TEST_M(CTag, Float, wxT("Kad: Read/Write floats"))
360 {
361 	byte packet[] = {
362 		0x02,
363 		/*Tag1*/0x04, 0x01, 0x00, 0xFF, 0x79, 0xe9, 0xf6, 0x42,
364 		/*Tag2*/0x04, 0x01, 0x00, 0xFF, 0x79, 0xd9, 0xd6, 0x42,
365 	};
366 
367 	TagPtrList taglist;
368 	ReadTagPtrList(taglist, packet, sizeof (packet));
369 	TagPtrList::iterator it = taglist.begin();
370 
371 	CheckTagData(*it++, TAG_SOURCETYPE, valid_tag_value((float) 123.456));
372 	CheckTagData(*it++, TAG_SOURCETYPE, valid_tag_value((float) 107.424751));
373 
374 	ASSERT_TRUE(it == taglist.end());
375 	test_taglist_serialization(taglist, packet, sizeof (packet));
376 	deleteTagPtrListEntries(&taglist);
377 }
378 
379 TEST_M(CTag, CMD4Hash, wxT("Kad: Read/Write CMD4Hash"))
380 {
381 	byte packet[] = {
382 		0x01,
383 		/*Tag1*/0x01,
384 		0x01, 0x00, 0xFF,
385 		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
386 		0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
387 	};
388 
389 	TagPtrList taglist;
390 	ReadTagPtrList(taglist, packet, sizeof (packet));
391 	TagPtrList::iterator it = taglist.begin();
392 
393 	CMD4Hash hash;
394 	ASSERT_TRUE(hash.Decode(std::string("000102030405060708090A0B0C0D0E0F")));
395 
396 	CheckTagData(*it++, TAG_SOURCETYPE, valid_tag_value(hash));
397 
398 	ASSERT_TRUE(it == taglist.end());
399 	test_taglist_serialization(taglist, packet, sizeof (packet));
400 	deleteTagPtrListEntries(&taglist);
401 }
402 
403 template<class T, class V>
check_single_kad_tag(byte * packet,size_t packet_len,T tagName,V tagValue)404 void check_single_kad_tag(byte* packet, size_t packet_len, T tagName, V tagValue)
405 {
406 	CMemFile buf(packet, packet_len);
407 	CONTEXT(wxT("Starting buffer: ") + toString(buf));
408 	CTag* tag = buf.ReadTag(true);
409 
410 	CheckTagData(tag, tagName, valid_tag_value(tagValue));
411 	{
412 		CONTEXT(wxT("Check end of buffer"));
413 		ASSERT_EQUALS(packet_len, buf.GetPosition());
414 	}
415 
416 	{
417 		CMemFile newbuf;
418 		newbuf.WriteTag(*tag);
419 
420 		CONTEXT(wxT("Serialized    : ") + toString(newbuf));
421 
422 		newbuf.Seek(0, wxFromStart);
423 		for (size_t i = 0; i < packet_len; i++) {
424 			CONTEXT(wxString::Format(wxT("Comparing byte #%d"), static_cast<int>(i)));
425 
426 			ASSERT_EQUALS(packet[i], newbuf.ReadUInt8());
427 		}
428 
429 		ASSERT_EQUALS(packet_len, buf.GetPosition());
430 	}
431 	delete tag;
432 }
433 
434 TEST_M(CTag, KadBsob, wxT("Kad: Read/Write BSOB"))
435 {
436 	byte packet[] = {
437 		/*Tag1*/ 0x0A, 0x01, 0x00, 0x02, 0x04, 0x01, 0x02, 0x03, 0x04,
438 	};
439 	byte raw_data[] = {0x01, 0x02, 0x03, 0x04};
440 	{
441 		CONTEXT(wxT("Create BSOBValue"));
442 		BSOBValue bsob(sizeof (raw_data), raw_data);
443 
444 		CONTEXT(wxT("check_single_kad_tag BSOBValue"));
445 		check_single_kad_tag(packet, sizeof (packet), TAG_FILESIZE, bsob);
446 	}
447 }
448 
449 TEST_M(CTag, KadInt64, wxT("Kad: Read/Write integer 64bit"))
450 {
451 	byte packet[] = {
452 		/*Tag1*/ 0x0b, 0x01, 0x00, 0x02, 0x10, 0x11, 0x12, 0x13, 0x20, 0x21, 0x22, 0x23, // 64 bit int
453 	};
454 	check_single_kad_tag(packet, sizeof (packet), TAG_FILESIZE, 0x2322212013121110LL);
455 }
456 
457 TEST_M(CTag, KadInt32, wxT("Kad: Read/Write integer 32bit"))
458 {
459 	byte packet[] = {
460 		/*Tag1*/ 0x03, 0x01, 0x00, 0x02, 0x12, 0x34, 0x56, 0x78, // 32 bit int
461 	};
462 	check_single_kad_tag(packet, sizeof (packet), TAG_FILESIZE, 0x78563412);
463 }
464 
465 TEST_M(CTag, KadInt16, wxT("Kad: Read/Write integer 16bit"))
466 {
467 	byte packet[] = {
468 		/*Tag1*/ 0x08, 0x01, 0x00, 0x02, 0x12, 0x34, // 16 bit int
469 	};
470 	check_single_kad_tag(packet, sizeof (packet), TAG_FILESIZE, 0x3412);
471 }
472 
473 TEST_M(CTag, KadInt8, wxT("Kad: Read/Write integer  8bit"))
474 {
475 	byte packet[] = {
476 		/*Tag1*/ 0x09, 0x01, 0x00, 0x02, 0x12, //  8 bit int
477 	};
478 	check_single_kad_tag(packet, sizeof (packet), TAG_FILESIZE, 0x12);
479 }
480 
481 TEST_M(CTag, ReadIntegers, wxT("Kad: Read/Write multiple integers"))
482 {
483 	byte packet[] = {
484 		0x08,
485 		/*Tag1*/ 0x03, 0x01, 0x00, 0x02, 0x12, 0x34, 0x56, 0x78, // 32 bit int
486 		/*Tag2*/ 0x08, 0x01, 0x00, 0x02, 0x12, 0x34, // 16 bit int
487 		/*Tag3*/ 0x09, 0x01, 0x00, 0x02, 0x12, //  8 bit int
488 		/*Tag4*/ 0x0b, 0x01, 0x00, 0x02, 0x10, 0x11, 0x12, 0x13, 0x20, 0x21, 0x22, 0x23, // 64 bit int
489 
490 		/*Tag5*/ 0x03, 0x01, 0x00, 0x02, 0x12, 0x34, 0x56, 0x78, // 32 bit int
491 		/*Tag6*/ 0x08, 0x01, 0x00, 0x02, 0x12, 0x34, // 16 bit int
492 		/*Tag7*/ 0x09, 0x01, 0x00, 0x02, 0x12, //  8 bit int
493 		/*Tag8*/ 0x0b, 0x01, 0x00, 0x02, 0x10, 0x11, 0x12, 0x13, 0x20, 0x21, 0x22, 0x23, // 64 bit int
494 	};
495 
496 	TagPtrList taglist;
497 	ReadTagPtrList(taglist, packet, sizeof (packet));
498 	TagPtrList::iterator it = taglist.begin();
499 
500 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(0x78563412));
501 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(0x3412));
502 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(0x12));
503 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(0x2322212013121110LL));
504 
505 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(0x78563412));
506 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(0x3412));
507 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(0x12));
508 	CheckTagData(*it++, TAG_FILESIZE, valid_tag_value(0x2322212013121110LL));
509 
510 	ASSERT_TRUE(it == taglist.end());
511 	test_taglist_serialization(taglist, packet, sizeof (packet));
512 	deleteTagPtrListEntries(&taglist);
513 }
514 
515 
516 #include <map>
517 
518 typedef std::map<wxString, wxString> TagNamesByString;
519 
520 TEST_M(CTag, KadTagNames, wxT("Kad: Test Kad tags (name=string) - write/read every valid tag name"))
521 {
522 	TagNamesByString tagNames;
523 
524 	tagNames[TAG_FILENAME] = wxT("TAG_FILENAME");
525 	tagNames[TAG_FILESIZE] = wxT("TAG_FILESIZE");
526 	tagNames[TAG_FILESIZE_HI] = wxT("TAG_FILESIZE_HI");
527 	tagNames[TAG_FILETYPE] = wxT("TAG_FILETYPE");
528 	tagNames[TAG_FILEFORMAT] = wxT("TAG_FILEFORMAT");
529 	tagNames[TAG_COLLECTION] = wxT("TAG_COLLECTION");
530 	tagNames[TAG_PART_PATH] = wxT("TAG_PART_PATH");
531 	tagNames[TAG_PART_HASH] = wxT("TAG_PART_HASH");
532 	tagNames[TAG_COPIED] = wxT("TAG_COPIED");
533 	tagNames[TAG_GAP_START] = wxT("TAG_GAP_START");
534 	tagNames[TAG_GAP_END] = wxT("TAG_GAP_END");
535 	tagNames[TAG_DESCRIPTION] = wxT("TAG_DESCRIPTION");
536 	tagNames[TAG_PING] = wxT("TAG_PING");
537 	tagNames[TAG_FAIL] = wxT("TAG_FAIL");
538 	tagNames[TAG_PREFERENCE] = wxT("TAG_PREFERENCE");
539 	tagNames[TAG_PORT] = wxT("TAG_PORT");
540 	tagNames[TAG_IP_ADDRESS] = wxT("TAG_IP_ADDRESS");
541 	tagNames[TAG_VERSION] = wxT("TAG_VERSION");
542 	tagNames[TAG_TEMPFILE] = wxT("TAG_TEMPFILE");
543 	tagNames[TAG_PRIORITY] = wxT("TAG_PRIORITY");
544 	tagNames[TAG_STATUS] = wxT("TAG_STATUS");
545 	tagNames[TAG_SOURCES] = wxT("TAG_SOURCES");
546 	tagNames[TAG_AVAILABILITY] = wxT("TAG_AVAILABILITY");
547 	tagNames[TAG_PERMISSIONS] = wxT("TAG_PERMISSIONS");
548 	tagNames[TAG_QTIME] = wxT("TAG_QTIME");
549 	tagNames[TAG_PARTS] = wxT("TAG_PARTS");
550 	tagNames[TAG_PUBLISHINFO] = wxT("TAG_PUBLISHINFO");
551 	tagNames[TAG_MEDIA_ARTIST] = wxT("TAG_MEDIA_ARTIST");
552 	tagNames[TAG_MEDIA_ALBUM] = wxT("TAG_MEDIA_ALBUM");
553 	tagNames[TAG_MEDIA_TITLE] = wxT("TAG_MEDIA_TITLE");
554 	tagNames[TAG_MEDIA_LENGTH] = wxT("TAG_MEDIA_LENGTH");
555 	tagNames[TAG_MEDIA_BITRATE] = wxT("TAG_MEDIA_BITRATE");
556 	tagNames[TAG_MEDIA_CODEC] = wxT("TAG_MEDIA_CODEC");
557 	tagNames[TAG_KADMISCOPTIONS] = wxT("TAG_KADMISCOPTIONS");
558 	tagNames[TAG_ENCRYPTION] = wxT("TAG_ENCRYPTION");
559 	tagNames[TAG_FILERATING] = wxT("TAG_FILERATING");
560 	tagNames[TAG_BUDDYHASH] = wxT("TAG_BUDDYHASH");
561 	tagNames[TAG_CLIENTLOWID] = wxT("TAG_CLIENTLOWID");
562 	tagNames[TAG_SERVERPORT] = wxT("TAG_SERVERPORT");
563 	tagNames[TAG_SERVERIP] = wxT("TAG_SERVERIP");
564 	tagNames[TAG_SOURCEUPORT] = wxT("TAG_SOURCEUPORT");
565 	tagNames[TAG_SOURCEPORT] = wxT("TAG_SOURCEPORT");
566 	tagNames[TAG_SOURCEIP] = wxT("TAG_SOURCEIP");
567 	tagNames[TAG_SOURCETYPE] = wxT("TAG_SOURCETYPE");
568 
569 	CMemFile buf;
570 	buf.WriteUInt8(tagNames.size());
571 	int counter = 0;
572 	// For each tagNames entry write an 8bit int tag (type:0x9)
573 	for (TagNamesByString::iterator it_name = tagNames.begin(); it_name != tagNames.end(); ++it_name) {
574 		buf.WriteUInt8(0x09); // 8 bit int tag type
575 
576 		buf.WriteUInt8(0x01); // single char string
577 		buf.WriteUInt8(0x00); //
578 
579         #if wxCHECK_VERSION(3, 1, 0)
580             wxCharBuffer b = wxConvISO8859_1.cWC2MB(it_name->first.c_str());
581         #else
582             wxCharBuffer b = wxConvISO8859_1.cWC2MB(it_name->first);
583         #endif
584 
585 		buf.WriteUInt8(((const char *)b)[0]); // Write string first char
586 		buf.WriteUInt8(counter++); // write tag value
587 	}
588 
589 	TagPtrList taglist;
590 	buf.Seek(0, wxFromStart);
591 	size_t packet_len = buf.GetLength();
592 	std::vector<byte> packet(packet_len);
593 	buf.Read(&packet[0], packet_len);
594 
595 	ReadTagPtrList(taglist, &packet[0], packet_len);
596 
597 	TagPtrList::iterator it = taglist.begin();
598 
599 	counter = 0;
600 	for (TagNamesByString::iterator it_name = tagNames.begin(); it_name != tagNames.end(); ++it_name) {
601 		CONTEXT(wxT("Testing tag name: ") + it_name->second);
602 		CheckTagData(*it++, it_name->first, valid_tag_value(counter++));
603 	}
604 
605 	ASSERT_TRUE(it == taglist.end());
606 	test_taglist_serialization(taglist, &packet[0], packet_len);
607 	deleteTagPtrListEntries(&taglist);
608 }
609 
610 typedef std::map<int, wxString> TagNamesByInt;
611 
612 TEST_M(CTag, ED2kTagNames, wxT("Ed2k: Test ed2k tags (name=id) - write/read every valid tag name"))
613 {
614 	TagNamesByInt tagNames;
615 
616 	tagNames[FT_FILENAME] = wxT("FT_FILENAME");
617 	tagNames[FT_FILESIZE] = wxT("FT_FILESIZE");
618 	tagNames[FT_FILESIZE_HI] = wxT("FT_FILESIZE_HI");
619 	tagNames[FT_FILETYPE] = wxT("FT_FILETYPE");
620 	tagNames[FT_FILEFORMAT] = wxT("FT_FILEFORMAT");
621 	tagNames[FT_LASTSEENCOMPLETE] = wxT("FT_LASTSEENCOMPLETE");
622 	tagNames[FT_TRANSFERRED] = wxT("FT_TRANSFERRED");
623 	tagNames[FT_GAPSTART] = wxT("FT_GAPSTART");
624 	tagNames[FT_GAPEND] = wxT("FT_GAPEND");
625 	tagNames[FT_PARTFILENAME] = wxT("FT_PARTFILENAME");
626 	tagNames[FT_OLDDLPRIORITY] = wxT("FT_OLDDLPRIORITY");
627 	tagNames[FT_STATUS] = wxT("FT_STATUS");
628 	tagNames[FT_SOURCES] = wxT("FT_SOURCES");
629 	tagNames[FT_PERMISSIONS] = wxT("FT_PERMISSIONS");
630 	tagNames[FT_OLDULPRIORITY] = wxT("FT_OLDULPRIORITY");
631 	tagNames[FT_DLPRIORITY] = wxT("FT_DLPRIORITY");
632 	tagNames[FT_ULPRIORITY] = wxT("FT_ULPRIORITY");
633 	tagNames[FT_KADLASTPUBLISHKEY] = wxT("FT_KADLASTPUBLISHKEY");
634 	tagNames[FT_KADLASTPUBLISHSRC] = wxT("FT_KADLASTPUBLISHSRC");
635 	tagNames[FT_FLAGS] = wxT("FT_FLAGS");
636 	tagNames[FT_DL_ACTIVE_TIME] = wxT("FT_DL_ACTIVE_TIME");
637 	tagNames[FT_CORRUPTEDPARTS] = wxT("FT_CORRUPTEDPARTS");
638 	tagNames[FT_DL_PREVIEW] = wxT("FT_DL_PREVIEW");
639 	tagNames[FT_KADLASTPUBLISHNOTES] = wxT("FT_KADLASTPUBLISHNOTES");
640 	tagNames[FT_AICH_HASH] = wxT("FT_AICH_HASH");
641 	tagNames[FT_COMPLETE_SOURCES] = wxT("FT_COMPLETE_SOURCES");
642 	tagNames[FT_PUBLISHINFO] = wxT("FT_PUBLISHINFO");
643 	tagNames[FT_ATTRANSFERRED] = wxT("FT_ATTRANSFERRED");
644 	tagNames[FT_ATREQUESTED] = wxT("FT_ATREQUESTED");
645 	tagNames[FT_ATACCEPTED] = wxT("FT_ATACCEPTED");
646 	tagNames[FT_CATEGORY] = wxT("FT_CATEGORY");
647 	tagNames[FT_ATTRANSFERREDHI] = wxT("FT_ATTRANSFERREDHI");
648 	tagNames[FT_MEDIA_ARTIST] = wxT("FT_MEDIA_ARTIST");
649 	tagNames[FT_MEDIA_ALBUM] = wxT("FT_MEDIA_ALBUM");
650 	tagNames[FT_MEDIA_TITLE] = wxT("FT_MEDIA_TITLE");
651 	tagNames[FT_MEDIA_LENGTH] = wxT("FT_MEDIA_LENGTH");
652 	tagNames[FT_MEDIA_BITRATE] = wxT("FT_MEDIA_BITRATE");
653 	tagNames[FT_MEDIA_CODEC] = wxT("FT_MEDIA_CODEC");
654 	tagNames[FT_FILERATING] = wxT("FT_FILERATING");
655 
656 
657 	CMemFile buf;
658 
659 	uint64 counter = 0;
660 	for (TagNamesByInt::iterator it_name = tagNames.begin(); it_name != tagNames.end(); ++it_name) {
661 		// m_uType
662 		buf.WriteUInt8(0x09 + 0x80);
663 		// m_uName
664 		buf.WriteUInt8(it_name->first);
665 		// 8 bit
666 		buf.WriteUInt8(counter++);
667 	}
668 
669 	buf.Seek(0, wxFromStart);
670 
671 	counter = 0;
672 	for (TagNamesByInt::iterator it_name = tagNames.begin(); it_name != tagNames.end(); ++it_name) {
673 		CONTEXT(wxString::Format(wxT("Reading tag#%") wxLongLongFmtSpec wxT("u"), counter));
674 		CTag* newtag = new CTag(buf, true);
675 		CheckTagName(it_name->first, newtag);
676 		CheckTagValue( valid_tag_value( counter ), newtag);
677 		delete newtag;
678 		counter++;
679 	}
680 }
681 
682 TEST_M(CTag, Ed2kBlob1, wxT("Ed2k: Read/Write BLOB - numeric tagname"))
683 {
684 	byte packet[] = {
685 		/*Tag1*/ 0x87, 0xFF, 0x04, 0x00, 0x00, 0x00,
686 		0x01, 0x02, 0x03, 0x04,
687 	};
688 
689 	CMemFile buf(packet, sizeof (packet));
690 	buf.Seek(0, wxFromStart);
691 	byte raw_data[] = {0x01, 0x02, 0x03, 0x04};
692 	{
693 		CONTEXT(wxT("Create BLOBValue"));
694 		BLOBValue blob(sizeof (raw_data), raw_data);
695 
696 		CTag tag(buf, true);
697 		CheckTagName(0xFF, &tag);
698 		CheckTagValue( valid_tag_value( blob ), &tag);
699 	}
700 }
701 
702 TEST_M(CTag, Ed2kBlob2, wxT("Ed2k: Read/Write BLOB - string tagname"))
703 {
704 	byte packet[] = {
705 		/*Tag1*/ 0x07, 0x02, 0x00, 'A', 'A', 0x04, 0x00, 0x00, 0x00,
706 		0x01, 0x02, 0x03, 0x04,
707 	};
708 
709 	CMemFile buf(packet, sizeof (packet));
710 	buf.Seek(0, wxFromStart);
711 	byte raw_data[] = {0x01, 0x02, 0x03, 0x04};
712 	{
713 		CONTEXT(wxT("Create BLOBValue"));
714 		BLOBValue blob(sizeof (raw_data), raw_data);
715 
716 		CTag tag(buf, true);
717 		CheckTagName(wxT("AA"), &tag);
718 		CheckTagValue( valid_tag_value( blob ), &tag);
719 	}
720 }
721