PageRenderTime 98ms CodeModel.GetById 51ms app.highlight 33ms RepoModel.GetById 11ms app.codeStats 0ms

/plugins/net.danieldietrich.protectedregions.core/src/test/xtend/net/danieldietrich/protectedregions/ProtectedRegionSupportTest.xtend

https://github.com/danieldietrich/xtext-protected-regions
Xtend | 264 lines | 214 code | 34 blank | 16 comment | 4 complexity | e92953ced8c6ab92275f08c325ab92f8 MD5 | raw file
  1package net.danieldietrich.protectedregions
  2
  3import static org.junit.Assert.*
  4
  5import com.google.inject.Guice
  6
  7import java.io.FileNotFoundException
  8import java.nio.charset.Charset
  9
 10import org.junit.Before
 11import org.junit.Test
 12
 13/**
 14 * Note: These test cases access the file system instead of passing
 15 *       CharSequences to simulate real parsing conditions.
 16 */
 17class ProtectedRegionSupportTest {
 18	
 19	extension ModelBuilder modelBuilder
 20	extension ParserFactory parserFactory
 21	extension ProtectedRegionSupport support
 22	
 23	static val BASE_DIR = "src/test/resources"
 24	static val CHARSET = Charset::forName("UTF-8")
 25	
 26	@Before
 27	def void setup() {
 28		val injector = Guice::createInjector
 29		modelBuilder = injector.getInstance(typeof(ModelBuilder))
 30		parserFactory = injector.getInstance(typeof(ParserFactory))
 31		support = injector.getInstance(typeof(ProtectedRegionSupport))
 32	}
 33	
 34	@Test
 35	def void mergeShouldMatchExpected() {
 36		parsingPreviousAndMergingCurrentShouldMatchExpected(javaParser, "protected")
 37	}
 38	
 39	@Test
 40	def void xmlParserShouldMatchExpected() {
 41		parsingPreviousAndMergingCurrentShouldMatchExpected(xmlParser, "xml")
 42	}
 43	
 44	@Test
 45	def void switchedRegionsParserShouldPreserveEnabledRegionsOnly() {
 46		parsingPreviousAndMergingCurrentShouldMatchExpected(javaParser, "switched")
 47	}
 48	
 49	@Test
 50	def void fillInShouldMatchExpected() {
 51		
 52		val parser = javaParser => [
 53			inverse = true
 54			resolver = new FillInRegionResolver
 55		]
 56		
 57		parsingPreviousAndMergingCurrentShouldMatchExpected(parser, "fill_in")
 58		
 59	}	
 60	
 61	def private parsingPreviousAndMergingCurrentShouldMatchExpected(ProtectedRegionParser parser, String fileNamePrefix) {
 62		
 63		val currentFile = '''src/test/resources/«fileNamePrefix»_current.txt'''.file
 64		val previousFile = '''src/test/resources/«fileNamePrefix»_previous.txt'''.file
 65		val expectedFile = '''src/test/resources/«fileNamePrefix»_expected.txt'''.file
 66
 67		// only support files relevant for this test case
 68		support.addParser(parser, previousFile.filter)
 69
 70		// only read previous content
 71		support.read(BASE_DIR.file, [CHARSET])
 72		
 73		val generatedContent = currentFile.read
 74		val mergedContent = support.merge(previousFile, generatedContent, [CHARSET]) // pass previous to use the correct parser
 75		val expectedContent = expectedFile.read
 76		
 77		assertEquals(expectedContent, mergedContent)
 78		
 79	}
 80
 81	@Test
 82	def void nonExistingFilesShouldByHandledGracefully() {
 83		support.merge("does_not_exist".file, "", [CHARSET])
 84	}
 85		
 86	@Test
 87	def void idsShouldBeUniquePerFile() {
 88		val file = "src/test/resources/non_unique_ids.txt".file
 89		support.addParser(javaParser, file.filter)
 90		try {
 91			support.read(BASE_DIR.file, [CHARSET])
 92			assertTrue("Duplicate marked region with id 'uniqueId' not detected.", false)
 93		} catch (IllegalStateException x) {
 94			assertEquals("Duplicate marked region with id 'uniqueId' detected", x.getMessage());
 95		}
 96	}
 97
 98	@Test
 99	def void scalaParserShouldReadNestedComments() {
100		
101		val regions = (scalaParser => [
102			resolver = new NestedCommentRegionResolver	
103		]).parse("src/test/resources/nested_comments.txt".file.read)
104		
105		// Scala does not recognize nested comment-like id's
106		assertTrue(regions.findFirst[id == "1234"] != null)
107		
108	}
109
110	@Test
111	def void javaParserShouldntReadNestedCommentsButDoesWhichIsOkInThisCase() {
112		
113		val regions = (javaParser => [
114			resolver = new NestedCommentRegionResolver	
115		]).parse("src/test/resources/nested_comments.txt".file.read)
116
117		// SPECIAL CASE
118		// ------------
119		// xpr reads:  /* PROTECTED REGION /*1234*/ ENABLED START */
120		// java reads: /* PROTECTED REGION /*1234*/
121		// -> remaining string invalid java:        ENABLED START */
122		//
123		// GOLDEN RULE: xtext-protected-regions reads valid code only
124		// => this case cannot occur
125		// => the following xpr behavior is ok:
126		assertTrue(regions.findFirst[id == "1234"] != null)
127		
128	}
129	
130	@Test
131	def void alternativeRegionNotationsShouldWorkAsWell() {
132		
133		val parser = parser("java")[
134			model[
135				comment("//")
136				comment("/*", "*/")
137				string('"').withEscape("\\")
138				string("'").withEscape("\\")
139			]
140		] => [
141			resolver = new SimpleRegionResolver
142		]
143		
144		parsingPreviousAndMergingCurrentShouldMatchExpected(parser, "simple")
145		
146	}
147	
148	@Test
149	def void xmlCDataShouldBeIgnored() {
150		val regions = xmlParser.parse("src/test/resources/ignore_xml_cdata.txt".file.read)
151		assertTrue(regions.findFirst[id == "no.id"] == null)
152	}
153	
154	@Test
155	def void javaStringsShouldBeIgnored() {
156		val regions = javaParser.parse("src/test/resources/ignore_java_strings.txt".file.read)
157		assertTrue(regions.findFirst[id == "no.id"] == null)
158	}
159
160	@Test
161	def void javaStringEscapesShouldBeIdentified() {
162		val regions = javaParser.parse("src/test/resources/ignore_java_string_escapes.txt".file.read)
163		assertTrue(regions.findFirst[id == "no.id"] == null)
164	}
165
166	@Test(expected = typeof(IllegalStateException))
167	def void locallyDuplicatedRegionIdsShouldBeDetected() {
168		support.addParser(javaParser, "src/test/resources/locally_duplicated_id.txt".file.filter)
169		support.read(BASE_DIR.file, [CHARSET])
170	}
171
172 	@Test(expected = typeof(IllegalStateException))
173	def void globallyDuplicatedRegionIdsShouldBeDetected() {
174		support.addParser(xmlParser => [
175			resolver = new DefaultGeneratedRegionResolver
176			inverse = true
177		], "src/test/resources/globally_duplicated_id1.txt".file.filter)
178		support.addParser(javaParser, "src/test/resources/globally_duplicated_id2.txt".file.filter)
179		support.read(BASE_DIR.file, [CHARSET])
180	}
181
182	@Test(expected = typeof(IllegalStateException))
183	def void missingStartMarkerShouldBeDetected() {
184		javaParser.parse("src/test/resources/missing_start_marker.txt".file.read)
185	}
186
187	@Test(expected = typeof(IllegalStateException))
188	def void missingNestedStartMarkerShouldBeDetected() {
189		javaParser.parse("src/test/resources/nested_start_marker.txt".file.read)
190	}
191	
192	@Test(expected = typeof(IllegalStateException))
193	def void missingEndMarkerAtEndOfFileShouldBeDetected() {
194		javaParser.parse("src/test/resources/missing_end_marker.txt".file.read)
195	}
196	
197	@Test
198	def void issue37ShouldBeSolved() {
199		javaParser.parse("src/test/resources/issue#37.txt".file.read)
200	}
201
202	def private file(CharSequence fileName) {
203		new JavaIoFile(new java.io.File(fileName.toString))
204	}
205	
206	def private filter(File file) {
207		new SingleFileFilter(file)
208	}
209
210	def private read(File file) {
211		if (!file.exists) throw new FileNotFoundException("File "+ file +" not found.")
212		file.read(CHARSET)
213	}
214	
215}
216
217@Data class SingleFileFilter extends FileFilter {
218	val File file
219	override accept(File file) {
220		_file.equals(file)
221	}
222}
223
224class NestedCommentRegionResolver extends RegionResolver {
225	
226	// example: PROTECTED REGION /*1234*/ START
227	static val PR_START = "PROTECTED\\s+REGION\\s+/\\*\\s*([0-9]+)\\s*\\*/\\s+(?:(ENABLED)\\s+)?START"
228	static val PR_END = "PROTECTED\\s+REGION\\s+END"
229	
230	new() { super(PR_START, PR_END) }
231	
232	override isEnabled(String regionStart) {
233		"ENABLED".equals(getEnabled(regionStart))
234	}
235	
236}
237
238class FillInRegionResolver extends RegionResolver {
239	
240	// example: GENERATED ID(1234) START
241	static val PR_START = "GENERATED\\s+ID\\s*\\(\\s*([0-9]+)\\s*\\)\\s+(?:(DISABLED)\\s+)?START"
242	static val PR_END = "GENERATED\\s+END"
243	
244	new() { super(PR_START, PR_END) }
245	
246	override isEnabled(String regionStart) {
247		!"DISABLED".equals(getEnabled(regionStart))
248	}
249	
250}
251
252class SimpleRegionResolver extends RegionResolver {
253	
254	// $(SomeClass.imports)-{
255	// }-$
256	static val ID = "[\\p{L}\\p{N}\\.:_$]*"
257	static val PR_START = "\\$\\(("+ ID +")\\)-\\{"
258	static val PR_END = "\\}-\\$"
259	
260	new() { super(PR_START, PR_END) }
261	
262	override isEnabled(String regionStart) { true }
263	
264}