Add generic HTML5LibTest class for performing HTML5lib tests

https://github.com/html5lib/html5lib-tests
This commit is contained in:
iska
2014-10-25 17:35:58 +02:00
parent 779fcf0a73
commit 0910290ef2
6 changed files with 272 additions and 0 deletions
+18
View File
@@ -13,6 +13,9 @@
624493AC19CD0CBE00BCDDF4 /* HTMLToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493AA19CD0CBE00BCDDF4 /* HTMLToken.h */; };
624493AD19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */; };
624493AE19CD0CBE00BCDDF4 /* HTMLToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */; };
624AC8FF19FBF59800BD3C4A /* HTMLTokens.h in Headers */ = {isa = PBXBuildFile; fileRef = 624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */; };
624AC90119FBF9ED00BD3C4A /* HTMLTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AC90019FBF9ED00BD3C4A /* HTMLTokenizerTests.m */; };
624AC90219FBF9ED00BD3C4A /* HTMLTokenizerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624AC90019FBF9ED00BD3C4A /* HTMLTokenizerTests.m */; };
625A14B019C7829400AD0C32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 625A14AF19C7829400AD0C32 /* Cocoa.framework */; };
625A14BA19C7829400AD0C32 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 625A14B819C7829400AD0C32 /* InfoPlist.strings */; };
625A14BE19C7829400AD0C32 /* HTMLKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 625A14BD19C7829400AD0C32 /* HTMLKit.m */; };
@@ -56,6 +59,8 @@
62AE594E19F9A17A0043F069 /* HTMLEOFToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 62AE594C19F9A17A0043F069 /* HTMLEOFToken.h */; };
62AE594F19F9A17A0043F069 /* HTMLEOFToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE594D19F9A17A0043F069 /* HTMLEOFToken.m */; };
62AE595019F9A17A0043F069 /* HTMLEOFToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 62AE594D19F9A17A0043F069 /* HTMLEOFToken.m */; };
62D8345919FB1AC4009205A9 /* HTML5LibTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D8345819FB1AC4009205A9 /* HTML5LibTest.m */; };
62D8345A19FB1AC4009205A9 /* HTML5LibTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D8345819FB1AC4009205A9 /* HTML5LibTest.m */; };
62F31FDD19E9DCCF007F0657 /* HTMLTokenizerEntities.h in Headers */ = {isa = PBXBuildFile; fileRef = 62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */; };
62F31FDE19E9DCCF007F0657 /* HTMLTokenizerEntities.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */; };
62F31FDF19E9DCCF007F0657 /* HTMLTokenizerEntities.m in Sources */ = {isa = PBXBuildFile; fileRef = 62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */; };
@@ -100,6 +105,8 @@
624493A919CCE84A00BCDDF4 /* HTMLTokenizerStates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerStates.h; sourceTree = "<group>"; };
624493AA19CD0CBE00BCDDF4 /* HTMLToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLToken.h; sourceTree = "<group>"; };
624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLToken.m; sourceTree = "<group>"; };
624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokens.h; sourceTree = "<group>"; };
624AC90019FBF9ED00BD3C4A /* HTMLTokenizerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTokenizerTests.m; sourceTree = "<group>"; };
625A14AC19C7829400AD0C32 /* HTMLKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HTMLKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
625A14AF19C7829400AD0C32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
625A14B219C7829400AD0C32 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
@@ -137,6 +144,8 @@
62AE594819F9948A0043F069 /* HTMLCharacterToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterToken.m; sourceTree = "<group>"; };
62AE594C19F9A17A0043F069 /* HTMLEOFToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLEOFToken.h; sourceTree = "<group>"; };
62AE594D19F9A17A0043F069 /* HTMLEOFToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLEOFToken.m; sourceTree = "<group>"; };
62D8345719FB1AC4009205A9 /* HTML5LibTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTML5LibTest.h; sourceTree = "<group>"; };
62D8345819FB1AC4009205A9 /* HTML5LibTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTML5LibTest.m; sourceTree = "<group>"; };
62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerCharacters.h; sourceTree = "<group>"; };
62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerEntities.h; sourceTree = "<group>"; };
62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTokenizerEntities.m; sourceTree = "<group>"; };
@@ -256,6 +265,9 @@
625A14CA19C7829400AD0C32 /* Tests */ = {
isa = PBXGroup;
children = (
62D8345719FB1AC4009205A9 /* HTML5LibTest.h */,
62D8345819FB1AC4009205A9 /* HTML5LibTest.m */,
624AC90019FBF9ED00BD3C4A /* HTMLTokenizerTests.m */,
625A14D019C7829400AD0C32 /* HTMLKitTests.m */,
625A14CB19C7829400AD0C32 /* Supporting Files */,
);
@@ -285,6 +297,7 @@
62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */,
62F31FDB19E9DCCF007F0657 /* HTMLTokenizerEntities.h */,
62F31FDC19E9DCCF007F0657 /* HTMLTokenizerEntities.m */,
624AC8FE19FBF4F700BD3C4A /* HTMLTokens.h */,
624493AA19CD0CBE00BCDDF4 /* HTMLToken.h */,
624493AB19CD0CBE00BCDDF4 /* HTMLToken.m */,
62AE594719F9948A0043F069 /* HTMLCharacterToken.h */,
@@ -311,6 +324,7 @@
buildActionMask = 2147483647;
files = (
62F873EB19E088C90062683C /* HTMLParser.h in Headers */,
624AC8FF19FBF59800BD3C4A /* HTMLTokens.h in Headers */,
62AE594419F992F30043F069 /* HTMLCommentToken.h in Headers */,
62AE594E19F9A17A0043F069 /* HTMLEOFToken.h in Headers */,
624493AC19CD0CBE00BCDDF4 /* HTMLToken.h in Headers */,
@@ -490,6 +504,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
624AC90219FBF9ED00BD3C4A /* HTMLTokenizerTests.m in Sources */,
62D8345A19FB1AC4009205A9 /* HTML5LibTest.m in Sources */,
625A14D119C7829400AD0C32 /* HTMLKitTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -519,6 +535,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
624AC90119FBF9ED00BD3C4A /* HTMLTokenizerTests.m in Sources */,
62D8345919FB1AC4009205A9 /* HTML5LibTest.m in Sources */,
625A150519C783FD00AD0C32 /* HTMLKitTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
+15
View File
@@ -0,0 +1,15 @@
//
// HTMLTokens.h
// HTMLKit
//
// Created by Iska on 25/10/14.
// Copyright (c) 2014 BrainCookie. All rights reserved.
//
#import "HTMLToken.h"
#import "HTMLCharacterToken.h"
#import "HTMLCommentToken.h"
#import "HTMLDOCTYPEToken.h"
#import "HTMLEOFToken.h"
#import "HTMLParseErrorToken.h"
#import "HTMLTagToken.h"
+22
View File
@@ -0,0 +1,22 @@
//
// HTML5LibTest.h
// HTMLKit
//
// Created by Iska on 25/10/14.
// Copyright (c) 2014 BrainCookie. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface HTML5LibTest : NSObject
@property (nonatomic, strong) NSString *description;
@property (nonatomic, strong) NSString *input;
@property (nonatomic, strong) NSArray *output;
@property (nonatomic, strong) NSArray *initialStates;
@property (nonatomic, strong) NSString *lastStartTag;
@property (nonatomic, assign) BOOL ignoreErrorOrder;
- (instancetype)initWithFixture:(NSDictionary *)fixture;
@end
+138
View File
@@ -0,0 +1,138 @@
//
// HTML5LibTest.m
// HTMLKit
//
// Created by Iska on 25/10/14.
// Copyright (c) 2014 BrainCookie. All rights reserved.
//
#import "HTML5LibTest.h"
#import "HTMLTokenizerStates.h"
#import "HTMLTokens.h"
@implementation HTML5LibTest
- (instancetype)initWithFixture:(NSDictionary *)fixture
{
self = [super init];
if (self) {
[self loadFixture:fixture];
}
return self;
}
- (void)loadFixture:(NSDictionary *)fixture
{
BOOL doubleEscaped = [fixture[@"doubleEscaped"] boolValue];
// Test Description
self.description = fixture[@"description"];
// Test Input
self.input = fixture[@"input"];
if (doubleEscaped) {
self.input = [self processDoubleEscaped:self.input];
}
// Test Output
NSMutableArray *tokens = [NSMutableArray array];
NSArray *outputs = fixture[@"output"];
for (NSArray *output in outputs) {
HTMLToken *token = [self processOutputToken:output doubleEscaped:doubleEscaped];
[tokens addObject:token];
}
self.output = tokens;
// Test Initial States
NSMutableArray *initialStates = [NSMutableArray array];
NSArray *states = fixture[@"initialStates"];
for (NSString *name in states) {
HTMLTokenizerState state = HTMLTokenizerStateData;
if ([name isEqualToString:@"PLAINTEXT state"]) {
state = HTMLTokenizerStatePLAINTEXT;
} else if ([name isEqualToString:@"RCDATA state"]) {
state = HTMLTokenizerStateRCDATA;
} else if ([name isEqualToString:@"RAWTEXT state"]) {
state = HTMLTokenizerStateRAWTEXT;
}
[initialStates addObject:@(state)];
}
if (initialStates.count == 0) {
[initialStates addObject:@(HTMLTokenizerStateData)];
}
self.initialStates = initialStates;
// Test Last Start Tag
self.lastStartTag = fixture[@"lastStartTag"];
// Ignore Error Order
self.ignoreErrorOrder = [fixture[@"ignoreErrorOrder"] boolValue];
}
- (HTMLToken *)processOutputToken:(NSArray *)output doubleEscaped:(BOOL)doubleEscaped
{
NSString *type = [output firstObject];
NSString *data = nil;
if (output.count > 1) {
NSString *data = [output lastObject];
if (doubleEscaped) {
data = [self processDoubleEscaped:data];
}
}
if ([type isEqualToString:@"Character"]) {
return [[HTMLCharacterToken alloc] initWithString:data];
} else if ([type isEqualToString:@"Comment"]) {
return [[HTMLCommentToken alloc] initWithData:data];
} else if ([type isEqualToString:@"DOCTYPE"]) {
HTMLDOCTYPEToken *token = [[HTMLDOCTYPEToken alloc] initWithName:data];
token.publicIdentifier = output[2];
token.systemIdentifier = output[3];
token.forceQuirks = ([output[4] boolValue] == NO);
return token;
} else if ([type isEqualToString:@"EndTag"]) {
return [[HTMLEndTagToken alloc] initWithTagName:data];
} else if ([type isEqualToString:@"ParseError"]) {
return [HTMLParseErrorToken new];
} else if ([type isEqualToString:@"StartTag"]) {
HTMLStartTagToken *token = [[HTMLStartTagToken alloc] initWithTagName:data];
NSDictionary *attributes = output[2];
for (NSString *name in attributes) {
NSString *value = [attributes objectForKey:name];
[token.attributes setObject:value forKey:name];
}
token.selfClosing = (output.count == 4);
return token;
}
return nil;
}
- (NSString *)processDoubleEscaped:(NSString *)string
{
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\\\u([0-9a-f]{4})"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)];
for(NSTextCheckingResult *match in [matches reverseObjectEnumerator]) {
NSRange hexRange = [match rangeAtIndex:2];
NSString *hexString = [string substringWithRange:hexRange];
NSScanner *scanner = [NSScanner scannerWithString:hexString];
unsigned int codepint;
[scanner scanHexInt:&codepint];
NSString *replacement = [NSString stringWithFormat:@"%C", (unichar)codepint];
NSRange matchRange = [match rangeAtIndex:1];
string = [string stringByReplacingCharactersInRange:matchRange withString:replacement];
}
return nil;
}
@end
+38
View File
@@ -7,6 +7,7 @@
//
#import <XCTest/XCTest.h>
#import "HTMLTokenizer.h"
@interface HTMLKitTests : XCTestCase
@@ -31,4 +32,41 @@
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
- (void)testX
{
NSString *s = @"<!doctype html>\n\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n\n <title>The HTML5 Herald</title>\n <meta name=\"description\" content=\"The HTML5 Herald\">\n <meta name=\"author\" content=\"SitePoint\">\n\n <link rel=\"stylesheet\" href=\"css/styles.css?v=1.0\">\n\n <!--[if lt IE 9]>\n <script src=\"http://html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n <![endif]-->\n</head>\n\n<body>\n <script src=\"js/scripts.js\"></script>\n</body>\n</html>";
HTMLTokenizer *t = [[HTMLTokenizer alloc] initWithString:s];
HTMLToken *token = nil;
do {
token = [t nextToken];
NSLog(@"%@", token);
} while (token !=nil && ![token isEOFToken]);
}
- (void)testY
{
NSString *string = @"\\u003Efoo\\uFEFFbar";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(\\\\u([0-9a-f]{4}))"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)];
for(NSTextCheckingResult *match in [matches reverseObjectEnumerator]) {
NSRange matchRange = [match rangeAtIndex:1];
NSRange hexRange = [match rangeAtIndex:2];
NSString *hexString = [string substringWithRange:hexRange];
NSScanner *scanner = [NSScanner scannerWithString:hexString];
unsigned int codepint;
[scanner scanHexInt:&codepint];
NSString *replacement = [NSString stringWithFormat:@"%C", (unichar)codepint];
string = [string stringByReplacingCharactersInRange:matchRange withString:replacement];
}
NSLog(@"%@", string);
}
@end
+41
View File
@@ -0,0 +1,41 @@
//
// HTMLTokenizerTests.m
// HTMLKit
//
// Created by Iska on 25/10/14.
// Copyright (c) 2014 BrainCookie. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <XCTest/XCTest.h>
#import "HTML5LibTest.h"
@interface HTMLTokenizerTests : XCTestCase
@end
@implementation HTMLTokenizerTests
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample {
// This is an example of a functional test case.
XCTAssert(YES, @"Pass");
}
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
@end