<commit_before>//
//  CLuceneSearchServiceTests.mm
//  BRFullTextSearch
//
//  Created by Matt on 7/5/13.
//  Copyright (c) 2013 Blue Rocket. Distributable under the terms of the Apache License, Version 2.0.
//

#import "CLuceneSearchServiceTests.h"

#import "BRSimpleIndexable.h"
#import "CLuceneSearchResult.h"
#import "CLuceneSearchResults.h"
#import "CLuceneSearchService.h"
#import "NSDate+BRFullTextSearchAdditions.h"

@implementation CLuceneSearchServiceTests {
	CLuceneSearchService *searchService;
	NSString *indexPath;
}

- (void)setUp {
	[super setUp];
	NSString *tmpIndexDir = [BRTestSupport temporaryPathWithPrefix:@"notes" suffix:nil directory:YES];
	[[NSFileManager defaultManager] createDirectoryAtPath:tmpIndexDir withIntermediateDirectories:YES attributes:nil error:nil];
	searchService = [[CLuceneSearchService alloc] initWithIndexPath:tmpIndexDir];
	searchService.bundle = self.bundle;
	indexPath = tmpIndexDir;
	
	// make sure this always starts at 0
	[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:[searchService userDefaultsIndexUpdateCountKey]];
}

- (BRSimpleIndexable *)createTestIndexableInstance {
	return [[BRSimpleIndexable alloc] initWithIdentifier:[BRTestSupport UUID] data:@{
								kBRSearchFieldNameTitle : @"My special note",
								kBRSearchFieldNameValue : @"This is a long winded note with really important details in it."
			}];
}

#pragma mark - Basic search

- (void)testIndexMultipleBRSimpleIndexablesAndSearchForResults {
	BRSimpleIndexable *n0 = [self createTestIndexableInstance];
	n0.date = [n0.date dateByAddingTimeInterval:-4]; // offset dates to test sorting
	BRSimpleIndexable *n1 = [self createTestIndexableInstance];
	n1.title = @"My other fancy note.";
	n1.value = @"This is a cool note with other stuff in it.";
	n1.date = [[NSDate new] dateByAddingTimeInterval:-2];
	BRSimpleIndexable *n2 = [self createTestIndexableInstance];
	n2.title = @"My pretty note.";
	n2.value = @"Oh this is a note, buddy.";
	n2.date = [NSDate new];
	
	[searchService addObjectsToIndexAndWait:@[n0, n1, n2] error:nil];
	
	NSString *n0Id = n0.uid;
	NSString *n1Id = n1.uid;
	NSString *n2Id = n2.uid;
	
	// first test individual results
	id<BRSearchResults> results0 = [searchService search:@"special"];
	STAssertEquals([results0 count], (NSUInteger)1, @"results count");
	__block NSUInteger count = 0;
	[results0 iterateWithBlock:^(NSUInteger index, id<BRSearchResult>result, BOOL *stop) {
		count++;
		STAssertEqualObjects([result identifier], n0Id, @"object ID");
	}];
	STAssertEquals(count, (NSUInteger)1, @"results iterated");
	
	id<BRSearchResults> results1 = [searchService search:@"fancy"];
	STAssertEquals([results1 count], (NSUInteger)1, @"results count");
	count = 0;
	[results1 iterateWithBlock:^(NSUInteger index, id<BRSearchResult>result, BOOL *stop) {
		count++;
		STAssertEqualObjects([result identifier], n1Id, @"object ID");
	}];
	STAssertEquals(count, (NSUInteger)1, @"results iterated");
	
	id<BRSearchResults> results2 = [searchService search:@"pretty"];
	STAssertEquals([results2 count], (NSUInteger)1, @"results count");
	count = 0;
	[results2 iterateWithBlock:^(NSUInteger index, id<BRSearchResult>result, BOOL *stop) {
		count++;
		STAssertEqualObjects([result identifier], n2Id, @"object ID");
	}];
	STAssertEquals(count, (NSUInteger)1, @"results iterated");
}

- (void)testOptimizeIndexFromUpdateThreshold {
	const NSInteger threshold = 4;
	BRSimpleIndexable *n0 = [self createTestIndexableInstance];
	searchService.indexUpdateOptimizeThreshold = threshold;
	
	for ( int i = 0; i < threshold; i++ ) {
		n0.title = [NSString stringWithFormat:@"Special note%d", i];
		[searchService addObjectsToIndexAndWait:@[n0] error:nil];
	}
	
	// at this point, we should have mutliple segment files, and updated count
	NSInteger updateCount = [[NSUserDefaults standardUserDefaults] integerForKey:[searchService userDefaultsIndexUpdateCountKey]];
	STAssertEquals(updateCount, threshold, @"update count");
	
	n0.title = [NSString stringWithFormat:@"Special note%d", threshold];
	[searchService addObjectsToIndexAndWait:@[n0] error:nil];
	
	updateCount = [[NSUserDefaults standardUserDefaults] integerForKey:[searchService userDefaultsIndexUpdateCountKey]];
	STAssertEquals(updateCount, (NSInteger)0, @"update count");
}

- (void)testGetResultsByIndex {
	BRSimpleIndexable *n0 = [self createTestIndexableInstance];
	n0.date = [n0.date dateByAddingTimeInterval:-4]; // offset dates to test sorting
	BRSimpleIndexable *n1 = [self createTestIndexableInstance];
	n1.title = @"My other fancy note.";
	n1.value = @"This is a cool note with other stuff in it.";
	n1.date = [[NSDate new] dateByAddingTimeInterval:-2];
	BRSimpleIndexable *n2 = [self createTestIndexableInstance];
	n2.title = @"My pretty note.";
	n2.value = @"Oh this is a note, buddy.";
	n2.date = [NSDate new];
	
	[searchService addObjectsToIndexAndWait:@[n0, n1, n2] error:nil];
	
	NSString *n0Id = n0.uid;
	NSString *n1Id = n1.uid;
	NSString *n2Id = n2.uid;
	
	// now search with a sort...
	id<BRSearchResults> sorted = [searchService search:@"note" sortBy:kBRSearchFieldNameTimestamp sortType:BRSearchSortTypeString ascending:YES];
	STAssertEquals([sorted count], (NSUInteger)3, @"sorted count");
	STAssertEqualObjects([sorted resultAtIndex:0].identifier, n0Id, @"object by index");
	STAssertEqualObjects([sorted resultAtIndex:1].identifier, n1Id, @"object by index");<commit_msg>Fix precision warnings from 64bit.<commit_after>//
//  CLuceneSearchServiceTests.mm
//  BRFullTextSearch
//
//  Created by Matt on 7/5/13.
//  Copyright (c) 2013 Blue Rocket. Distributable under the terms of the Apache License, Version 2.0.
//

#import "CLuceneSearchServiceTests.h"

#import "BRSimpleIndexable.h"
#import "CLuceneSearchResult.h"
#import "CLuceneSearchResults.h"
#import "CLuceneSearchService.h"
#import "NSDate+BRFullTextSearchAdditions.h"

@implementation CLuceneSearchServiceTests {
	CLuceneSearchService *searchService;
	NSString *indexPath;
}

- (void)setUp {
	[super setUp];
	NSString *tmpIndexDir = [BRTestSupport temporaryPathWithPrefix:@"notes" suffix:nil directory:YES];
	[[NSFileManager defaultManager] createDirectoryAtPath:tmpIndexDir withIntermediateDirectories:YES attributes:nil error:nil];
	searchService = [[CLuceneSearchService alloc] initWithIndexPath:tmpIndexDir];
	searchService.bundle = self.bundle;
	indexPath = tmpIndexDir;
	
	// make sure this always starts at 0
	[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:[searchService userDefaultsIndexUpdateCountKey]];
}

- (BRSimpleIndexable *)createTestIndexableInstance {
	return [[BRSimpleIndexable alloc] initWithIdentifier:[BRTestSupport UUID] data:@{
								kBRSearchFieldNameTitle : @"My special note",
								kBRSearchFieldNameValue : @"This is a long winded note with really important details in it."
			}];
}

#pragma mark - Basic search

- (void)testIndexMultipleBRSimpleIndexablesAndSearchForResults {
	BRSimpleIndexable *n0 = [self createTestIndexableInstance];
	n0.date = [n0.date dateByAddingTimeInterval:-4]; // offset dates to test sorting
	BRSimpleIndexable *n1 = [self createTestIndexableInstance];
	n1.title = @"My other fancy note.";
	n1.value = @"This is a cool note with other stuff in it.";
	n1.date = [[NSDate new] dateByAddingTimeInterval:-2];
	BRSimpleIndexable *n2 = [self createTestIndexableInstance];
	n2.title = @"My pretty note.";
	n2.value = @"Oh this is a note, buddy.";
	n2.date = [NSDate new];
	
	[searchService addObjectsToIndexAndWait:@[n0, n1, n2] error:nil];
	
	NSString *n0Id = n0.uid;
	NSString *n1Id = n1.uid;
	NSString *n2Id = n2.uid;
	
	// first test individual results
	id<BRSearchResults> results0 = [searchService search:@"special"];
	STAssertEquals([results0 count], (NSUInteger)1, @"results count");
	__block NSUInteger count = 0;
	[results0 iterateWithBlock:^(NSUInteger index, id<BRSearchResult>result, BOOL *stop) {
		count++;
		STAssertEqualObjects([result identifier], n0Id, @"object ID");
	}];
	STAssertEquals(count, (NSUInteger)1, @"results iterated");
	
	id<BRSearchResults> results1 = [searchService search:@"fancy"];
	STAssertEquals([results1 count], (NSUInteger)1, @"results count");
	count = 0;
	[results1 iterateWithBlock:^(NSUInteger index, id<BRSearchResult>result, BOOL *stop) {
		count++;
		STAssertEqualObjects([result identifier], n1Id, @"object ID");
	}];
	STAssertEquals(count, (NSUInteger)1, @"results iterated");
	
	id<BRSearchResults> results2 = [searchService search:@"pretty"];
	STAssertEquals([results2 count], (NSUInteger)1, @"results count");
	count = 0;
	[results2 iterateWithBlock:^(NSUInteger index, id<BRSearchResult>result, BOOL *stop) {
		count++;
		STAssertEqualObjects([result identifier], n2Id, @"object ID");
	}];
	STAssertEquals(count, (NSUInteger)1, @"results iterated");
}

- (void)testOptimizeIndexFromUpdateThreshold {
	const NSInteger threshold = 4;
	BRSimpleIndexable *n0 = [self createTestIndexableInstance];
	searchService.indexUpdateOptimizeThreshold = threshold;
	
	for ( NSInteger i = 0; i < threshold; i++ ) {
		n0.title = [NSString stringWithFormat:@"Special note%ld", (long)i];
		[searchService addObjectsToIndexAndWait:@[n0] error:nil];
	}
	
	// at this point, we should have mutliple segment files, and updated count
	NSInteger updateCount = [[NSUserDefaults standardUserDefaults] integerForKey:[searchService userDefaultsIndexUpdateCountKey]];
	STAssertEquals(updateCount, threshold, @"update count");
	
	n0.title = [NSString stringWithFormat:@"Special note%ld", (long)threshold];
	[searchService addObjectsToIndexAndWait:@[n0] error:nil];
	
	updateCount = [[NSUserDefaults standardUserDefaults] integerForKey:[searchService userDefaultsIndexUpdateCountKey]];
	STAssertEquals(updateCount, (NSInteger)0, @"update count");
}

- (void)testGetResultsByIndex {
	BRSimpleIndexable *n0 = [self createTestIndexableInstance];
	n0.date = [n0.date dateByAddingTimeInterval:-4]; // offset dates to test sorting
	BRSimpleIndexable *n1 = [self createTestIndexableInstance];
	n1.title = @"My other fancy note.";
	n1.value = @"This is a cool note with other stuff in it.";
	n1.date = [[NSDate new] dateByAddingTimeInterval:-2];
	BRSimpleIndexable *n2 = [self createTestIndexableInstance];
	n2.title = @"My pretty note.";
	n2.value = @"Oh this is a note, buddy.";
	n2.date = [NSDate new];
	
	[searchService addObjectsToIndexAndWait:@[n0, n1, n2] error:nil];
	
	NSString *n0Id = n0.uid;
	NSString *n1Id = n1.uid;
	NSString *n2Id = n2.uid;
	
	// now search with a sort...
	id<BRSearchResults> sorted = [searchService search:@"note" sortBy:kBRSearchFieldNameTimestamp sortType:BRSearchSortTypeString ascending:YES];
	STAssertEquals([sorted count], (NSUInteger)3, @"sorted count");
	STAssertEqualObjects([sorted resultAtIndex:0].identifier, n0Id, @"object by index");
	STAssertEqualObjects([sorted resultAtIndex:1].identifier, n1Id, @"object by index");
{'fraction_non_alphanumeric': 0.12450392247346562, 'fraction_numerical': 0.016797415782187356, 'mean_word_length': 6.195219123505976, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 17, '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': '523454', 'n_tokens_mistral': 3691, 'n_tokens_neox': 3410, 'n_words': 851}