using System.Collections.Generic;
using System.Net.Sockets;
using Microsoft.VisualStudio.TestTools.UnitTesting;
public ushort QuestionCount;
public ushort AnswerCount;
public ushort AuthorityCount;
public ushort AdditionalCount;
public struct DNSQuestion
private static Dictionary<string, string> _records = new Dictionary<string, string>()
{ "example.com", "192.168.1.1" },
{ "google.com", "8.8.8.8" },
{ "test.local", "127.0.0.1" }
public static string DomainNameFromDNSFormat(byte[] data, int offset, out int newOffset)
if (data == null || data.Length == 0)
throw new ArgumentException("Data cannot be null or empty", nameof(data));
StringBuilder domainName = new StringBuilder();
int currentOffset = offset;
while ((length = data[currentOffset++]) != 0)
if (domainName.Length > 0)
domainName.Append(Encoding.ASCII.GetString(data, currentOffset, length));
newOffset = currentOffset;
return domainName.ToString();
public static byte[] DomainNameToDNSFormat(string domainName)
if (string.IsNullOrEmpty(domainName))
throw new ArgumentNullException(nameof(domainName), "Domain name cannot be null or empty.");
List<byte> dnsFormat = new List<byte>();
string[] labels = domainName.Split('.');
foreach (string label in labels)
dnsFormat.Add((byte)label.Length);
dnsFormat.AddRange(Encoding.ASCII.GetBytes(label));
return dnsFormat.ToArray();
public static byte[] IPAddressToBytes(string ipAddress)
if (string.IsNullOrEmpty(ipAddress))
throw new ArgumentNullException(nameof(ipAddress), "IP address cannot be null or empty.");
return IPAddress.Parse(ipAddress).GetAddressBytes();
public static string BytesToIPAddress(byte[] bytes)
throw new ArgumentNullException(nameof(bytes), "IP address cannot be null or empty.");
return new IPAddress(bytes).ToString();
public static byte[] CreateDNSPacket(DNSHeader header, DNSQuestion question, DNSAnswer? answer)
if(question.QNAME == null)
throw new ArgumentNullException(nameof(question), "DNS Question cannot be null.");
List<byte> packet = new List<byte>();
packet.AddRange(BitConverter.GetBytes(header.Id).Reverse());
packet.AddRange(BitConverter.GetBytes(header.Flags).Reverse());
packet.AddRange(BitConverter.GetBytes(header.QuestionCount).Reverse());
packet.AddRange(BitConverter.GetBytes(header.AnswerCount).Reverse());
packet.AddRange(BitConverter.GetBytes(header.AuthorityCount).Reverse());
packet.AddRange(BitConverter.GetBytes(header.AdditionalCount).Reverse());
packet.AddRange(DomainNameToDNSFormat(question.QNAME));
packet.AddRange(BitConverter.GetBytes(question.QTYPE).Reverse());
packet.AddRange(BitConverter.GetBytes(question.QCLASS).Reverse());
if (answer.Value.NAME == null || answer.Value.RDATA == null)
throw new ArgumentNullException(nameof(answer), "DNS Answer properties cannot be null when answer is provided.");
packet.AddRange(DomainNameToDNSFormat(answer.Value.NAME));
packet.AddRange(BitConverter.GetBytes(answer.Value.TYPE).Reverse());
packet.AddRange(BitConverter.GetBytes(answer.Value.CLASS).Reverse());
packet.AddRange(BitConverter.GetBytes(answer.Value.TTL).Reverse());
packet.AddRange(BitConverter.GetBytes(answer.Value.RDLENGTH).Reverse());
packet.AddRange(IPAddressToBytes(answer.Value.RDATA));
public static DNSHeader ParseDNSHeader(byte[] data)
if (data == null || data.Length < 12)
throw new ArgumentException("Invalid DNS header data.", nameof(data));
Id = BitConverter.ToUInt16(data, 0),
Flags = BitConverter.ToUInt16(data, 2),
QuestionCount = BitConverter.ToUInt16(data, 4),
AnswerCount = BitConverter.ToUInt16(data, 6),
AuthorityCount = BitConverter.ToUInt16(data, 8),
AdditionalCount = BitConverter.ToUInt16(data, 10)
public static DNSQuestion ParseDNSQuestion(byte[] data, int offset, out int newOffset)
throw new ArgumentNullException(nameof(data), "DNS Question cannot be null.");
string qname = DomainNameFromDNSFormat(data, offset, out newOffset);
ushort qtype = BitConverter.ToUInt16(data.Skip(newOffset).Take(2).Reverse().ToArray(), 0);
ushort qclass = BitConverter.ToUInt16(data.Skip(newOffset).Take(2).Reverse().ToArray(), 0);
public static DNSAnswer? ResolveDNSQuery(string domainName)
if (string.IsNullOrEmpty(domainName))
throw new ArgumentNullException(nameof(domainName), "Domain name cannot be null or empty.");
if (_records.TryGetValue(domainName, out string ipAddress))
public static void Main()
Console.WriteLine("š Discovering and Running Tests...\n");
int totalPassed = 0, totalFailed = 0;
var testClasses = Assembly.GetExecutingAssembly()
.Where(t => t.GetCustomAttribute<TestClassAttribute>() != null);
foreach (var testClass in testClasses)
Console.WriteLine($"š Running tests in: {testClass.Name}");
(int passed, int failed) = RunTests(testClass);
Console.WriteLine("\nš FINAL SUMMARY:");
Console.WriteLine($"ā
Total Passed: {totalPassed}");
Console.WriteLine($"ā Total Failed: {totalFailed}");
Console.WriteLine($"š Total Tests: {totalPassed + totalFailed}");
Console.WriteLine("\nā
Test execution completed.");
private static (int passed, int failed) RunTests(Type testClassType)
object testInstance = Activator.CreateInstance(testClassType);
MethodInfo[] testMethods = testClassType
.GetMethods(BindingFlags.Instance | BindingFlags.Public)
.Where(m => m.GetCustomAttribute<TestMethodAttribute>() != null)
int passed = 0, failed = 0;
foreach (var method in testMethods)
method.Invoke(testInstance, null);
Console.WriteLine($" ā
{method.Name} PASSED");
catch (TargetInvocationException ex)
Console.WriteLine($" ā {method.Name} FAILED: {ex.InnerException?.Message ?? ex.Message}");
Console.WriteLine($" ā ļø {method.Name} ERROR: {ex.Message}");
public class DNSServerTests
public void DomainNameFromDNSFormat_ValidInput_ReturnsCorrectDomainName()
byte[] data = { 3, 116, 101, 115, 116, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0 };
string expected = "test.example.com";
string actual = DNSServer.DomainNameFromDNSFormat(data, offset, out newOffset);
Assert.AreEqual(expected, actual);
Assert.AreEqual(18, newOffset);
[ExpectedException(typeof(ArgumentException))]
public void DomainNameFromDNSFormat_NullData_ThrowsArgumentException()
DNSServer.DomainNameFromDNSFormat(data, offset, out newOffset);
[ExpectedException(typeof(ArgumentException))]
public void DomainNameFromDNSFormat_EmptyData_ThrowsArgumentException()
byte[] data = new byte[0];
DNSServer.DomainNameFromDNSFormat(data, offset, out newOffset);
public void DomainNameToDNSFormat_ValidInput_ReturnsCorrectBytes()
string domainName = "test.example.com";
byte[] expected = { 3, 116, 101, 115, 116, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0 };
byte[] actual = DNSServer.DomainNameToDNSFormat(domainName);
CollectionAssert.AreEqual(expected, actual);
[ExpectedException(typeof(ArgumentNullException))]
public void DomainNameToDNSFormat_NullDomainName_ThrowsArgumentNullException()
DNSServer.DomainNameToDNSFormat(null);
[ExpectedException(typeof(ArgumentNullException))]
public void DomainNameToDNSFormat_EmptyDomainName_ThrowsArgumentNullException()
DNSServer.DomainNameToDNSFormat("");
public void IPAddressToBytes_ValidIP_ReturnsCorrectBytes()
string ipAddress = "192.168.1.1";
byte[] expected = { 192, 168, 1, 1 };
byte[] actual = DNSServer.IPAddressToBytes(ipAddress);
CollectionAssert.AreEqual(expected, actual);
[ExpectedException(typeof(ArgumentNullException))]
public void IPAddressToBytes_NullIP_ThrowsArgumentNullException()
DNSServer.IPAddressToBytes(null);
[ExpectedException(typeof(ArgumentNullException))]
public void IPAddressToBytes_EmptyIP_ThrowsArgumentNullException()
DNSServer.IPAddressToBytes("");
[ExpectedException(typeof(FormatException))]
public void IPAddressToBytes_InvalidIP_ThrowsFormatException()
DNSServer.IPAddressToBytes("invalid ip");
public void BytesToIPAddress_ValidBytes_ReturnsCorrectIPAddress()
byte[] bytes = { 192, 168, 1, 1 };
string expected = "192.168.1.1";
string actual = DNSServer.BytesToIPAddress(bytes);
Assert.AreEqual(expected, actual);
[ExpectedException(typeof(ArgumentNullException))]
public void BytesToIPAddress_NullBytes_ThrowsArgumentNullException()
DNSServer.BytesToIPAddress(null);
public void CreateDNSPacket_ValidInputWithAnswer_ReturnsCorrectPacket()
DNSHeader header = new DNSHeader { Id = 1, Flags = 0, QuestionCount = 1, AnswerCount = 1, AuthorityCount = 0, AdditionalCount = 0 };
DNSQuestion question = new DNSQuestion { QNAME = "example.com", QTYPE = 1, QCLASS = 1 };
DNSAnswer answer = new DNSAnswer { NAME = "example.com", TYPE = 1, CLASS = 1, TTL = 60, RDLENGTH = 4, RDATA = "192.168.1.1" };
byte[] packet = DNSServer.CreateDNSPacket(header, question, answer);
Assert.IsNotNull(packet);
Assert.IsTrue(packet.Length > 0);
public void CreateDNSPacket_ValidInputWithoutAnswer_ReturnsCorrectPacket()
DNSHeader header = new DNSHeader { Id = 1, Flags = 0, QuestionCount = 1, AnswerCount = 0, AuthorityCount = 0, AdditionalCount = 0 };
DNSQuestion question = new DNSQuestion { QNAME = "example.com", QTYPE = 1, QCLASS = 1 };
byte[] packet = DNSServer.CreateDNSPacket(header, question, null);
Assert.IsNotNull(packet);
Assert.IsTrue(packet.Length > 0);
[ExpectedException(typeof(ArgumentNullException))]
public void CreateDNSPacket_NullQuestion_ThrowsArgumentNullException()
DNSHeader header = new DNSHeader();
DNSAnswer answer = new DNSAnswer();
DNSServer.CreateDNSPacket(header, default, answer);
[ExpectedException(typeof(ArgumentNullException))]
public void CreateDNSPacket_NullAnswerProperties_ThrowsArgumentNullException()
DNSHeader header = new DNSHeader();
DNSQuestion question = new DNSQuestion { QNAME = "example.com" };
DNSAnswer answer = new DNSAnswer { NAME = null, RDATA = null };
DNSServer.CreateDNSPacket(header, question, answer);
public void ParseDNSHeader_ValidData_ReturnsCorrectHeader()
byte[] data = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C };
DNSHeader expected = new DNSHeader { Id = 0x0201, Flags = 0x0403, QuestionCount = 0x0605, AnswerCount = 0x0807, AuthorityCount = 0x0A09, AdditionalCount = 0x0C0B };
DNSHeader actual = DNSServer.ParseDNSHeader(data);
Assert.AreEqual(expected.Id, BitConverter.ToUInt16(BitConverter.GetBytes(actual.Id).Reverse().ToArray(), 0));
Assert.AreEqual(expected.Flags, BitConverter.ToUInt16(BitConverter.GetBytes(actual.Flags).Reverse().ToArray(), 0));
Assert.AreEqual(expected.QuestionCount, BitConverter.ToUInt16(BitConverter.GetBytes(actual.QuestionCount).Reverse().ToArray(), 0));
Assert.AreEqual(expected.AnswerCount, BitConverter.ToUInt16(BitConverter.GetBytes(actual.AnswerCount).Reverse().ToArray(), 0));
Assert.AreEqual(expected.AuthorityCount, BitConverter.ToUInt16(BitConverter.GetBytes(actual.AuthorityCount).Reverse().ToArray(), 0));
Assert.AreEqual(expected.AdditionalCount, BitConverter.ToUInt16(BitConverter.GetBytes(actual.AdditionalCount).Reverse().ToArray(), 0));
[ExpectedException(typeof(ArgumentException))]
public void ParseDNSHeader_NullData_ThrowsArgumentException()
DNSServer.ParseDNSHeader(null);
[ExpectedException(typeof(ArgumentException))]
public void ParseDNSHeader_ShortData_ThrowsArgumentException()
byte[] data = new byte[11];
DNSServer.ParseDNSHeader(data);
public void ParseDNSQuestion_ValidData_ReturnsCorrectQuestion()
byte[] data = { 3, 116, 101, 115, 116, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 1, 0, 1 };
DNSQuestion expected = new DNSQuestion { QNAME = "test.example.com", QTYPE = 1, QCLASS = 1 };
DNSQuestion actual = DNSServer.ParseDNSQuestion(data, offset, out newOffset);
Assert.AreEqual(expected.QNAME, actual.QNAME);
Assert.AreEqual(expected.QTYPE, actual.QTYPE);
Assert.AreEqual(expected.QCLASS, actual.QCLASS);
Assert.AreEqual(22, newOffset);
[ExpectedException(typeof(ArgumentNullException))]
public void ParseDNSQuestion_NullData_ThrowsArgumentNullException()
DNSServer.ParseDNSQuestion(null, 0, out _);
public void ResolveDNSQuery_ExistingDomain_ReturnsCorrectAnswer()
string domainName = "example.com";
DNSAnswer? expected = new DNSAnswer { NAME = "example.com", TYPE = 1, CLASS = 1, TTL = 60, RDLENGTH = 4, RDATA = "192.168.1.1" };
DNSAnswer? actual = DNSServer.ResolveDNSQuery(domainName);
Assert.AreEqual(expected.Value.NAME, actual.Value.NAME);
Assert.AreEqual(expected.Value.TYPE, actual.Value.TYPE);
Assert.AreEqual(expected.Value.CLASS, actual.Value.CLASS);
Assert.AreEqual(expected.Value.TTL, actual.Value.TTL);
Assert.AreEqual(expected.Value.RDLENGTH, actual.Value.RDLENGTH);
Assert.AreEqual(expected.Value.RDATA, actual.Value.RDATA);
public void ResolveDNSQuery_NonExistingDomain_ReturnsNull()
string domainName = "nonexistent.com";
DNSAnswer? actual = DNSServer.ResolveDNSQuery(domainName);
[ExpectedException(typeof(ArgumentNullException))]
public void ResolveDNSQuery_NullDomainName_ThrowsArgumentNullException()
DNSServer.ResolveDNSQuery(null);