<commit_before>import XCTest
@testable import worldcities

class TestModelListSearch:XCTestCase
{
    private let kStringEmpty:String = ""
    private let kStringWithSpaces:String = "   "
    private let kStringWithNewLine:String = "\n"
    private let kStringWithTab:String = "\t"
    private let kStringWithReturn:String = "\r"
    private let kStringUpperCaseA:String = "A"
    private let kStringLowerCaseA:String = "a"
    private let kStringPercent:String = "%"
    private let kStringAAndPercent:String = "a%"
    private let kStringAmsterdam:String = "amsterdam"
    private let kWaitExpectation:TimeInterval = 600
    
    func testSearchItems()
    {
        let itemsExpectation:XCTestExpectation = expectation(
            description:"items loaded")
        
        let modelList:ModelList = ModelList()
        modelList.loadItems
        {
            itemsExpectation.fulfill()
        }
        
        waitForExpectations(timeout:kWaitExpectation)
        { [weak self] (error:Error?) in
            
            self?.inputEmpty(modelList:modelList)
            self?.inputSpaces(modelList:modelList)
            self?.inputTab(modelList:modelList)
            self?.inputReturn(modelList:modelList)
            self?.inputUpperCase(modelList:modelList)
            self?.inputLowerCase(modelList:modelList)
            self?.inputEqualsLowerUpper(modelList:modelList)
            self?.inputInvalidString(modelList:modelList)
            self?.inputValidAndInvalid(modelList:modelList)
            self?.resultsSorted(modelList:modelList)
            self?.searchSpecificCity(modelList:modelList)
        }
    }
    
    //MARK: private
    
    private func inputEmpty(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringEmpty)
        let foundCount:Int = foundItems.count
        let totalCount:Int = modelList.items.count
        
        XCTAssertEqual(
            foundCount,
            totalCount,
            "failed searching with empty string")
    }
    
    private func inputSpaces(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringWithSpaces)
        let foundCount:Int = foundItems.count
        let totalCount:Int = modelList.items.count
        
        XCTAssertEqual(
            foundCount,
            totalCount,
            "failed searching with spaces on input")
    }
    
    private func inputTab(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringWithTab)
        let foundCount:Int = foundItems.count
        let totalCount:Int = modelList.items.count
        
        XCTAssertEqual(
            foundCount,
            totalCount,
            "failed searching with tab on input")
    }
    
    private func inputReturn(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringWithReturn)
        let foundCount:Int = foundItems.count
        let totalCount:Int = modelList.items.count
        
        XCTAssertEqual(
            foundCount,
            totalCount,
            "failed searching with carriage return on input")
    }
    
    private func inputUpperCase(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringUpperCaseA)
        let foundCount:Int = foundItems.count
        
        XCTAssertGreaterThan(
            foundCount,
            0,
            "failed searching with upper case strings")
    }
    
    private func inputLowerCase(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringLowerCaseA)
        let foundCount:Int = foundItems.count
        
        XCTAssertGreaterThan(
            foundCount,
            0,
            "failed searching with lower case strings")
    }
    
    private func inputEqualsLowerUpper(modelList:ModelList)
    {
        let foundLower:[ModelListItem] = modelList.searchItems(
            forInput:kStringLowerCaseA)
        let foundUpper:[ModelListItem] = modelList.searchItems(
            forInput:kStringUpperCaseA)
        let countLower:Int = foundLower.count
        let countUpper:Int = foundUpper.count
        
        XCTAssertEqual(
            countLower,
            countUpper,
            "lower case search should be similar as upper case search")
    }
    
    private func inputInvalidString(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringPercent)
        let foundCount:Int = foundItems.count
        
        XCTAssertLessThan(
            foundCount,
            1,
            "search should be empty when looking for special characters")
    }
    
    private func inputValidAndInvalid(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringAAndPercent)
        let foundCount:Int = foundItems.count
        
        XCTAssertLessThan(
            foundCount,
            1,
            "search should be empty when looking for special characters")
    }
    
    private func resultsSorted(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringLowerCaseA)
        let foundCount:Int = foundItems.count
        
        if foundCount > 1
        {
            let foundA:String = foundItems[0].compareString
            let foundB:String = foundItems[1].compareString
            
            let comparison:ComparisonResult = foundA.compare(foundB)
            
            XCTAssertNotEqual(
                comparison,
                ComparisonResult.orderedDescending,
                "results are not sorted")
        }
    }
    
    private func searchSpecificCity(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringAmsterdam)
        let foundCount:Int = foundItems.count
        
        XCTAssertGreaterThan(
            foundCount,
            0,
            "failed looking for a specific city")
        
        for item:ModelListItem in foundItems
        {
            let displayString:String = item.displayString.lowercased()
            let containsAmsterdam:Bool = displayString.contains(kStringAmsterdam)
            
            XCTAssertTrue(
                containsAmsterdam,
                "failed looking for specific city")
        }
    }
}
<commit_msg>Add test validating results<commit_after>import XCTest
@testable import worldcities

class TestModelListSearch:XCTestCase
{
    private let kStringEmpty:String = ""
    private let kStringWithSpaces:String = "   "
    private let kStringWithNewLine:String = "\n"
    private let kStringWithTab:String = "\t"
    private let kStringWithReturn:String = "\r"
    private let kStringUpperCaseA:String = "A"
    private let kStringLowerCaseA:String = "a"
    private let kStringPercent:String = "%"
    private let kStringAAndPercent:String = "a%"
    private let kStringAmsterdam:String = "amsterdam"
    private let kWaitExpectation:TimeInterval = 600
    
    func testSearchItems()
    {
        let itemsExpectation:XCTestExpectation = expectation(
            description:"items loaded")
        
        let modelList:ModelList = ModelList()
        modelList.loadItems
        {
            itemsExpectation.fulfill()
        }
        
        waitForExpectations(timeout:kWaitExpectation)
        { [weak self] (error:Error?) in
            
            self?.inputEmpty(modelList:modelList)
            self?.inputSpaces(modelList:modelList)
            self?.inputTab(modelList:modelList)
            self?.inputReturn(modelList:modelList)
            self?.inputUpperCase(modelList:modelList)
            self?.inputLowerCase(modelList:modelList)
            self?.inputEqualsLowerUpper(modelList:modelList)
            self?.inputInvalidString(modelList:modelList)
            self?.inputValidAndInvalid(modelList:modelList)
            self?.resultsSorted(modelList:modelList)
            self?.resultsAreValid(modelList:modelList)
            self?.searchSpecificCity(modelList:modelList)
        }
    }
    
    //MARK: private
    
    private func inputEmpty(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringEmpty)
        let foundCount:Int = foundItems.count
        let totalCount:Int = modelList.items.count
        
        XCTAssertEqual(
            foundCount,
            totalCount,
            "failed searching with empty string")
    }
    
    private func inputSpaces(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringWithSpaces)
        let foundCount:Int = foundItems.count
        let totalCount:Int = modelList.items.count
        
        XCTAssertEqual(
            foundCount,
            totalCount,
            "failed searching with spaces on input")
    }
    
    private func inputTab(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringWithTab)
        let foundCount:Int = foundItems.count
        let totalCount:Int = modelList.items.count
        
        XCTAssertEqual(
            foundCount,
            totalCount,
            "failed searching with tab on input")
    }
    
    private func inputReturn(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringWithReturn)
        let foundCount:Int = foundItems.count
        let totalCount:Int = modelList.items.count
        
        XCTAssertEqual(
            foundCount,
            totalCount,
            "failed searching with carriage return on input")
    }
    
    private func inputUpperCase(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringUpperCaseA)
        let foundCount:Int = foundItems.count
        
        XCTAssertGreaterThan(
            foundCount,
            0,
            "failed searching with upper case strings")
    }
    
    private func inputLowerCase(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringLowerCaseA)
        let foundCount:Int = foundItems.count
        
        XCTAssertGreaterThan(
            foundCount,
            0,
            "failed searching with lower case strings")
    }
    
    private func inputEqualsLowerUpper(modelList:ModelList)
    {
        let foundLower:[ModelListItem] = modelList.searchItems(
            forInput:kStringLowerCaseA)
        let foundUpper:[ModelListItem] = modelList.searchItems(
            forInput:kStringUpperCaseA)
        let countLower:Int = foundLower.count
        let countUpper:Int = foundUpper.count
        
        XCTAssertEqual(
            countLower,
            countUpper,
            "lower case search should be similar as upper case search")
    }
    
    private func inputInvalidString(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringPercent)
        let foundCount:Int = foundItems.count
        
        XCTAssertLessThan(
            foundCount,
            1,
            "search should be empty when looking for special characters")
    }
    
    private func inputValidAndInvalid(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringAAndPercent)
        let foundCount:Int = foundItems.count
        
        XCTAssertLessThan(
            foundCount,
            1,
            "search should be empty when looking for special characters")
    }
    
    private func resultsSorted(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringLowerCaseA)
        let foundCount:Int = foundItems.count
        
        if foundCount > 1
        {
            let foundA:String = foundItems[0].compareString
            let foundB:String = foundItems[1].compareString
            
            let comparison:ComparisonResult = foundA.compare(foundB)
            
            XCTAssertNotEqual(
                comparison,
                ComparisonResult.orderedDescending,
                "results are not sorted")
        }
    }
    
    private func resultsAreValid(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringLowerCaseA)
        
        for item:ModelListItem in foundItems
        {
            let displayString:String = item.displayString
            let firstLetter:String = String(
                displayString[displayString.startIndex]).lowercased()
            
            XCTAssertEqual(
                firstLetter,
                kStringLowerCaseA,
                "search results are not similar to query")
        }
    }
    
    private func searchSpecificCity(modelList:ModelList)
    {
        let foundItems:[ModelListItem] = modelList.searchItems(
            forInput:kStringAmsterdam)
        let foundCount:Int = foundItems.count
        
        XCTAssertGreaterThan(
            foundCount,
            0,
            "failed looking for a specific city")
        
        for item:ModelListItem in foundItems
        {
            let displayString:String = item.displayString.lowercased()
            let containsAmsterdam:Bool = displayString.contains(kStringAmsterdam)
            
            XCTAssertTrue(
                containsAmsterdam,
                "failed looking for specific city")
        }
    }
}

{'fraction_non_alphanumeric': 0.06795066003029647, 'fraction_numerical': 0.0015869580898795355, 'mean_word_length': 2.0363556723609286, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '806597', 'n_tokens_mistral': 3611, 'n_tokens_neox': 3567, 'n_words': 718}