DEV Community

Adam.S
Adam.S

Posted on • Edited on • Originally published at bas-man.dev

Swift: Deconstruct SPF: Qualifier and MechanismKind

In this article I will be looking at defining the enums for Qualifier and MechanismKind. I will also be adding tests to ensure that the functions work as expected. Further I will implement a simple asMechanism() as a proof of concept.

Qualifier

As mentioned in an earlier article. The Qualifier will consist of the following values.

  • + Pass
  • - Fail
  • ~ SoftFail
  • ? Neutral
  • None

I expect that I will want to be able to obtain the character value (rawValue)
at some point in the future.

Definition

enum Qualifier: String { case Pass case Fail case SoftFail case Neutral case None func get() -> String { switch self { case .Pass: return "+" case .Fail: return "-" case .SoftFail: return "~" case .Neutral: return "?" case .None: return "" } } } 
Enter fullscreen mode Exit fullscreen mode

At this point I have diverged from the original definition. This gave me a chance to look at the switch statement in Swift. I think will change this in a refactor session, as I expect to be able to access the Raw Value. Scroll down to find the actual documentation.

Testing

To make testing a little cleaner and manageable moving forward. I also created a new file under DeconfSpfTests called DeconfSpfQualifierTests.swift.

This contains the following code.

import XCTest @testable import DeconSpf; final class SPFQualifierTests: XCTestCase { func testQualifierPass() { let Q = Qualifier.Pass; XCTAssertEqual(Q.get(), "+"); } func testQualifierFail() { let Q = Qualifier.Fail; XCTAssertEqual(Q.get(), "-"); } func testQualifierSoftFail() { let Q = Qualifier.SoftFail; XCTAssertEqual(Q.get(), "~"); } func testQualifierNeutral() { let Q = Qualifier.Neutral; XCTAssertEqual(Q.get(), "?"); } func testQualifierNone() { let Q = Qualifier.None; XCTAssertEqual(Q.get(), ""); } static var allTests = [ ("testQualifierPass", testQualifierPass), ("testQualifierFail", testQualifierFail), ("testQualifierSoftFail", testQualifierSoftFail), ("testQualifierNeutral", testQualifierNeutral), ("testQualifierNone", testQualifierNone), ] } 
Enter fullscreen mode Exit fullscreen mode
  • Note: The class name needs to be unique
    • final class SPFQualifierTests: XCTestCase
    • I am using SPFQualifierTests

MechanismKind

I took the same approach here with MechanismKind.

Definition

enum MechanismKind { case Redirect, Include, A, MX, ip4, ip6, All; func get() -> String { switch self { case .Redirect: return "redirect=" case .Include: return "include:" case .A: return "a" case .MX: return "mx" case .ip4: return "ip4:" case .ip6: return "ip6:" case .All: return "all" } } } 
Enter fullscreen mode Exit fullscreen mode

Testing

I also again created a new test file called DeconfSpfMechanismKindTests.

This also has a unique class name SPFMechanimsKindTests.

import XCTest @testable import DeconSpf; final class SPFMechanimsKindTests: XCTestCase { func testMechanimsKindRedirect() { let MK = MechanismKind.Redirect; XCTAssertEqual(MK.get(), "redirect="); } func testMechanimsKindInclude() { let MK = MechanismKind.Include; XCTAssertEqual(MK.get(), "include:"); } func testMechanimsKindA() { let MK = MechanismKind.A; XCTAssertEqual(MK.get(), "a"); } func testMechanimsKindMX() { let MK = MechanismKind.MX; XCTAssertEqual(MK.get(), "mx"); } func testMechanimsKindIp4() { let MK = MechanismKind.ip4; XCTAssertEqual(MK.get(), "ip4:"); } func testMechanimsKindIp6() { let MK = MechanismKind.ip6; XCTAssertEqual(MK.get(), "ip6:"); } func testMechanimsKindAll() { let MK = MechanismKind.All; XCTAssertEqual(MK.get(), "all"); } static var allTests = [ ("testMechanismKindRedirect", testMechanimsKindRedirect), ("testMechanismKindInclude", testMechanimsKindInclude), ("testMechanismKindA", testMechanimsKindA), ("testMechanismKindMX", testMechanimsKindMX), ("testMechanismKindIp4", testMechanimsKindIp4), ("testMechanismKindIp6", testMechanimsKindIp6), ("testMechanismKindAll", testMechanimsKindAll), ] } 
Enter fullscreen mode Exit fullscreen mode

asMechanism

Here I would refer you to the documentation on Strings and Characters.

Code

I have updated struct Mechanism as shown below

struct Mechanims { --snip-- func asMechanism() -> String { var mechanismString = String(); // TODO: Qualifier // Access the string for this mechanism's kind. mechanismString += self.kind.get(); // Access the string for the mechanim mechanismString += self.mechanism; return mechanismString; } --snip-- } 
Enter fullscreen mode Exit fullscreen mode

Tests

I now have my previous test working as well as a few new ones.

func testAsMechanismIp4() { let Mech = Mechanism(k: MechanismKind.ip4, q: Qualifier.None, m: "192.168.1.0/24"); XCTAssertEqual(Mech.asMechanism(), "ip4:192.168.1.0/24"); } func testAsMechanismIp6() { let Mech = Mechanism(k: MechanismKind.ip6, q: Qualifier.None, m: "X:X:X:X/16"); XCTAssertEqual(Mech.asMechanism(), "ip6:X:X:X:X/16"); } func testAsMechanismRedirect() { let Mech = Mechanism(k: MechanismKind.Redirect, q: Qualifier.None, m: "_spf.example.com"); XCTAssertEqual(Mech.asMechanism(), "redirect=_spf.example.com"); } func testAsMechanismInclude() { let Mech = Mechanism(k: MechanismKind.Include, q: Qualifier.None, m: "_spf1.example.com"); XCTAssertEqual(Mech.asMechanism(), "include:_spf1.example.com"); } func testAsMechanismA() { let Mech = Mechanism(k: MechanismKind.A, q: Qualifier.None, m: ""); XCTAssertEqual(Mech.asMechanism(), "a"); } func testAsMechanismMx() { let Mech = Mechanism(k: MechanismKind.MX, q: Qualifier.None, m: ""); XCTAssertEqual(Mech.asMechanism(), "mx"); } 
Enter fullscreen mode Exit fullscreen mode

Note that these tests are not complete. And do not yet cover all cases. In particular these tests will fail with several examples of A and MX Mechanisms.

The code for this project can now be found here.

This is the diff between Initial and Initial-asMechanism.

Closing

Today I implemented an initial get() function for both Qualifier and MechanismKind. I also did an initial implementation for asMechanism().

Top comments (0)