DEV Community

Adam.S
Adam.S

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

Swift: Deconstruct SPF: Struct Mechanism

Today, I will start on building out the functionality of the struct Mechanism.

This will involve creating some tests, and basic functions.

Instantiate the Mechanism Struct

We have our struct defined as such:

struct Mechanism {
    var kind: MechanismKind;
    var qualifier: Qualifier;
    var mechanism: String;

    init(k: MechanismKind, q: Qualifier, m: String) {
        kind = k;
        qualifier = q;
        mechanism = m;
    }
    func mechanismString() -> String {
        self.mechanism;
    }
    func whatKind() -> MechanismKind {
        return self.kind;
    }
    func isPass() -> Bool {
        return self.qualifier == Qualifier.Pass;
    }
    func isFail() -> Bool {
        return self.qualifier == Qualifier.Fail;
    }
    func isSoftFail() -> Bool {
        return self.qualifier == Qualifier.SoftFail;
    }
    func isNeutral() -> Bool {
        return self.qualifier == Qualifier.Neutral;
    }
    func isNone() -> Bool {
        return self.qualifier == Qualifier.None;
    }
}
Enter fullscreen mode Exit fullscreen mode

init

This will instantiate the struct. Provide what kind of mechanism it is. Its qualifier, and the value of its mechanism.

mechanismString

This will allow us to access the information stored in mechanism as a simple String

isPass

This will return Bool of true if the Qualifier is Pass

isFail

This will return Bool of true if the Qualifier is Fail

isSoftFail

This will return Bool of true if the Qualifier is SoftFail

isNeutral

This will return Bool of true if the Qualifier is Neutral

isNone

This will return Bool of true if the Qualifier is None

whatKind

This will help us understand if the mechanism represents a redirect, A, or some other mechanism.

Testing

For this we need to take a look at Tests/DeconSpfTests/DeconSpfTests.swift.

Within this file we have the following initial set of code.

import XCTest
@testable import DeconSpf;

final class SPFTests: XCTestCase {

    func testMechanismRedirect() {
        let Mech = Mechanism(k: MechanismKind.Redirect, q: Qualifier.None, m: "test.com");
        XCTAssertEqual(Mech.mechanismString(), "test.com");
        XCTAssertEqual(Mech.whatKind(), MechanismKind.Redirect);
        XCTAssertNotEqual(Mech.whatKind(), MechanismKind.A);
        XCTAssertEqual(Mech.isNone(), true);
    }
    func testMechanismInclude() {
        let Mech = Mechanism(k: MechanismKind.Include, q: Qualifier.Pass, m: "_spf.test.com");
        XCTAssertEqual(Mech.mechanismString(), "_spf.test.com");
        XCTAssertEqual(Mech.whatKind(), MechanismKind.Include);
        XCTAssertNotEqual(Mech.whatKind(), MechanismKind.Redirect);
        XCTAssertNotEqual(Mech.whatKind(), MechanismKind.A);
        XCTAssertEqual(Mech.isPass(), true);
    }
    static var allTests = [
        ("testMechanismRedirect", testMechanismRedirect),
        ("testMechanismInclude", testMechanismInclude),
    ]
}
Enter fullscreen mode Exit fullscreen mode

Let's break down each test function.

func testMechanismRedirect() {
    let Mech = Mechanism(k: MechanismKind.Redirect, q: Qualifier.None, m: "test.com");
    XCTAssertEqual(Mech.mechanismString(), "test.com");
    XCTAssertEqual(Mech.whatKind(), MechanismKind.Redirect);
    XCTAssertNotEqual(Mech.whatKind(), MechanismKind.A);
    XCTAssertEqual(Mech.isNone(), true);
}
Enter fullscreen mode Exit fullscreen mode

What are is happening here:

  1. Instantiate Mech and then we make four assertions.
  2. mechanismString() matches "test.com"
  3. whatKind() matches MechanismKind.Redirect
  4. The MechanismKind is not MechanismKind.A
  5. isNone() is true
func testMechanismInclude() {
    let Mech = Mechanism(k: MechanismKind.Include, q: Qualifier.Pass, m: "_spf.test.com");
    XCTAssertEqual(Mech.mechanismString(), "_spf.test.com");
    XCTAssertEqual(Mech.whatKind(), MechanismKind.Include);
    XCTAssertNotEqual(Mech.whatKind(), MechanismKind.Redirect);
    XCTAssertNotEqual(Mech.whatKind(), MechanismKind.A);
    XCTAssertEqual(Mech.isPass(), true);
}
Enter fullscreen mode Exit fullscreen mode

This does the same basic tests, but for a mechanism that should be of MechanismKind.Include.

Testing

swift test
Enter fullscreen mode Exit fullscreen mode

Output

[6/6] Linking DeconSpfPackageTests
Test Suite 'All tests' started at 2021-05-13 15:09:48.435
Test Suite 'DeconSpfPackageTests.xctest' started at 2021-05-13 15:09:48.436
Test Suite 'SPFTests' started at 2021-05-13 15:09:48.436
Test Case '-[DeconSpfTests.SPFTests testMechanismInclude]' started.
Test Case '-[DeconSpfTests.SPFTests testMechanismInclude]' passed (0.082 seconds).
Test Case '-[DeconSpfTests.SPFTests testMechanismRedirect]' started.
Test Case '-[DeconSpfTests.SPFTests testMechanismRedirect]' passed (0.000 seconds).
Test Suite 'SPFTests' passed at 2021-05-13 15:09:48.519.
  Executed 2 tests, with 0 failures (0 unexpected) in 0.083 (0.083) seconds
Test Suite 'DeconSpfPackageTests.xctest' passed at 2021-05-13 15:09:48.519.
  Executed 2 tests, with 0 failures (0 unexpected) in 0.083 (0.083) seconds
Test Suite 'All tests' passed at 2021-05-13 15:09:48.519.
  Executed 2 tests, with 0 failures (0 unexpected) in 0.083 (0.084) seconds

Enter fullscreen mode Exit fullscreen mode

Let's add a new test

We want to be able to get a string representation of the mechanism as it was originally seen.

If I had an initially mechanism of ip4:x.x.x.x which was stored as

  • kind: MechanismKind.Ip4
  • qualifier: Qualifier.None
  • mechanism: "x.x.x.x"

I should be able to call mech.asMechanism() and get ip4:x.x.x.x in return.

So let's make a test for this. (Expect failure)

We update the DeconSpfTests.swift with the following.

func testAsMechanism() {
    let Mech = Mechanism(k: MechanismKind.ip4, q: Qualifier.None, m: "192.168.1.0/24");
    XCTAssertEqual(Mech.asMechanism(), "ip4:192.168.1.0/24");
}
static var allTests = [
    ("testMechanismRedirect", testMechanismRedirect),
    ("testMechanismInclude", testMechanismInclude),
    ("testAsMechanism", testAsMechanism),
]
Enter fullscreen mode Exit fullscreen mode

We add this test to the allTests so that it will be run with the others.

Xcode also complains

Value of type 'Mechanism' has no member 'asMechanism'.

This is because I have not yet defined a member function named asMechanism() on the Mechanism struct.

The code for this project can now be found here.

This is the diff between the initial commit and the current code.

Closing

That's it for today. In the next article. I will look at returning values based on the Qualifier type. These will be needed to build the string for asMechanism()

Top comments (0)