DetailTableView.m 6.87 KB
Newer Older
1 2 3 4 5 6 7 8
//
//  DetailViewController.m
//  LinphoneTester
//
//  Created by guillaume on 28/05/2014.
//
//

9
#import "DetailTableView.h"
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
10
#import "MasterView.h"
Benjamin REIS's avatar
Benjamin REIS committed
11
#include "linphonetester/liblinphone_tester.h"
12
#import "Log.h"
13

14
static NSString *const kAllTestsName = @"Run All tests";
15 16 17

@implementation TestItem

18 19 20 21 22 23 24 25
- (id)initWithName:(NSString *)name fromSuite:(NSString *)suite {
	self = [super init];
	if (self) {
		self.name = name;
		self.suite = suite;
		self.state = TestStateIdle;
	}
	return self;
26 27
}

28 29
+ (TestItem *)testWithName:(NSString *)name fromSuite:(NSString *)suite {
	return [[TestItem alloc] initWithName:name fromSuite:suite];
30 31
}

32 33
- (NSString *)description {
	return [NSString stringWithFormat:@"{suite:'%@', test:'%@', state:%d}", _suite, _name, _state];
34 35 36 37
}

@end

38
@interface DetailTableView () {
39 40
	NSMutableArray *_tests;
	BOOL in_progress;
41
}
42
@property(strong, nonatomic) UIPopoverController *masterPopoverController;
43 44 45
- (void)configureView;
@end

46
@implementation DetailTableView
47 48 49

#pragma mark - Managing the detail item

50 51 52 53 54 55 56 57
- (void)setDetailItem:(id)newDetailItem {
	if (_detailItem != newDetailItem) {
		_detailItem = newDetailItem;

		// Update the view.
		[self configureView];
		[self.tableView reloadData];
	}
58

59 60 61
	if (self.masterPopoverController != nil) {
		[self.masterPopoverController dismissPopoverAnimated:YES];
	}
62 63
}

64 65 66 67 68
- (void)addTestsFromSuite:(NSString *)suite {
	int count = bc_tester_nb_tests([suite UTF8String]);

	for (int i = 0; i < count; i++) {
		const char *test_name = bc_tester_test_name([suite UTF8String], i);
69 70 71 72 73
		if (test_name) {
			NSString *testName = [NSString stringWithUTF8String:test_name];
			TestItem *item = [[TestItem alloc] initWithName:testName fromSuite:suite];
			[_tests addObject:item];
		}
74 75 76
	}
}

77
- (void)configureView {
78 79 80 81 82 83
	_tests = [[NSMutableArray alloc] initWithCapacity:0];
	if (self.detailItem == nil) {
		return;
	}

	if ([self.detailItem isEqualToString:@"All"]) {
84
		// dont sort tests if we use all suites at once
85
		for (int i = 0; i < bc_tester_nb_suites(); i++) {
86 87 88 89
			const char *suite = bc_tester_suite_name(i);
			if (suite) {
				[self addTestsFromSuite:[NSString stringWithUTF8String:suite]];
			}
90 91 92
		}
	} else {
		[self addTestsFromSuite:self.detailItem];
93 94 95
		[_tests sortUsingComparator:^(TestItem *obj1, TestItem *obj2) {
		  return [obj1.name compare:obj2.name];
		}];
96
	}
97 98
	// suite name not used for this one
	[_tests insertObject:[TestItem testWithName:kAllTestsName fromSuite:self.detailItem] atIndex:0];
99 100
}

101 102
- (void)viewDidLoad {
	[super viewDidLoad];
103
	// Do any additional setup after loading the view, typically from a nib.
104
	[self configureView];
105 106
}

107 108 109
- (void)didReceiveMemoryWarning {
	[super didReceiveMemoryWarning];
	// Dispose of any resources that can be recreated.
110 111 112 113 114
}

#pragma mark - Tableview

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
115
	return 1;
116 117
}

118 119
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
	return _tests.count;
120 121
}

122
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
123 124 125 126 127
	static NSString *kCellId = @"testCellIdentifier";
	UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellId forIndexPath:indexPath];
	if (cell == nil) {
		cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCellId];
	}
128

129
	TestItem *test = _tests[indexPath.row];
130 131 132
	cell.textLabel.text = [NSString stringWithFormat:@"%@/%@", test.suite, test.name];
	NSString *image = nil;
	switch (test.state) {
Gautier Pelloux-Prayer's avatar
Gautier Pelloux-Prayer committed
133 134 135 136 137 138 139 140 141 142 143 144
		case TestStateIdle:
			image = nil;
			break;
		case TestStatePassed:
			image = @"test_passed";
			break;
		case TestStateInProgress:
			image = @"test_inprogress";
			break;
		case TestStateFailed:
			image = @"test_failed";
			break;
145 146 147 148
	}
	if (image) {
		image = [[NSBundle mainBundle] pathForResource:image ofType:@"png"];
		cell.imageView.image = [UIImage imageWithContentsOfFile:image];
149 150 151
	} else {
		[cell.imageView setImage:nil];
	}
152
	return cell;
153 154
}

155 156
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
	return NO;
157 158
}

159
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
160 161 162 163 164 165 166 167 168 169 170
	[tableView deselectRowAtIndexPath:indexPath animated:FALSE];
	if (indexPath.row == 0) {
		// we should run all tests
		NSMutableArray *paths = [[NSMutableArray alloc] init];
		for (int i = 1; i < _tests.count; i++) {
			[paths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
		}
		[self launchTest:paths];
	} else {
		[self launchTest:@[ indexPath ]];
	}
171 172
}

173 174 175
- (void)updateItem:(NSArray *)paths withAnimation:(BOOL)animate {
	[self.tableView reloadRowsAtIndexPaths:paths
						  withRowAnimation:animate ? UITableViewRowAnimationFade : UITableViewRowAnimationNone];
176 177
}

178
- (void)launchTest:(NSArray *)paths {
179
	if (in_progress) {
180
		LOGE(@"Test already in progress");
181 182
		return;
	}
183

184
	in_progress = TRUE;
185 186 187 188 189
	for (NSIndexPath *index in paths) {
		TestItem *test = _tests[index.row];
		test.state = TestStateInProgress;
	}
	[self updateItem:paths withAnimation:FALSE];
190 191 192 193

	dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

	dispatch_async(queue, ^{
194 195 196 197 198 199 200 201 202 203 204
	  for (NSIndexPath *index in paths) {
		  TestItem *test = _tests[index.row];
		  LOGI(@"Should launch test %@", test);
		  NSString *testSuite = test.suite;
		  if ([test.suite isEqualToString:@"All"]) {
			  testSuite = nil;
		  }
		  NSString *testName = test.name;
		  if ([test.name isEqualToString:kAllTestsName]) {
			  testName = nil;
		  }
205 206 207 208 209 210
		  BOOL fail = NO;
		  @try {
			  fail = bc_tester_run_tests([testSuite UTF8String], [testName UTF8String], NULL);
		  } @catch (NSException *e) {
			  fail = YES;
		  }
211 212 213 214 215 216 217
		  if (fail) {
			  LOGW(@"Test Failed!");
			  test.state = TestStateFailed;
		  } else {
			  LOGI(@"Test Passed!");
			  test.state = TestStatePassed;
		  }
218
		  
219
		  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
220
              [self.tableView scrollToRowAtIndexPath:index atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
221 222
			[self updateItem:paths withAnimation:TRUE];
		  });
223
	  }
224
	  in_progress = FALSE;
225
	});
226 227
}

228 229
#pragma mark - Split view

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
- (void)splitViewController:(UISplitViewController *)splitController
	 willHideViewController:(UIViewController *)viewController
		  withBarButtonItem:(UIBarButtonItem *)barButtonItem
	   forPopoverController:(UIPopoverController *)popoverController {
	barButtonItem.title = NSLocalizedString(@"Master", @"Master");
	[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
	self.masterPopoverController = popoverController;
}

- (void)splitViewController:(UISplitViewController *)splitController
	 willShowViewController:(UIViewController *)viewController
  invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
	// Called when the view is shown again in the split view, invalidating the button and popover controller.
	[self.navigationItem setLeftBarButtonItem:nil animated:YES];
	self.masterPopoverController = nil;
245 246 247
}

@end