blob: 5ffa764741e52d44f296e6615346cf8149de0968 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 Sebastian Zarnekow and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Sebastian Zarnekow - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.tests.builder;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.tests.util.Util;
import junit.framework.Test;
public class Bug544921Test extends BuilderTests {
public Bug544921Test(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(Bug544921Test.class);
}
public void testCompilerRegression() throws JavaModelException, Exception {
IPath projectPath = env.addProject("Bug544921Test", "1.8"); //$NON-NLS-1$
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.addClass(projectPath, "a", "Test", //$NON-NLS-1$ //$NON-NLS-2$
"package a;\n" +
"import java.util.EnumMap;\n" +
"enum E {}\n" +
"public class Test {\n" +
" Object x = new EnumMap<E, String>(E.class) {\n" +
" static final long serialVersionUID = 1;\n" +
" {\n" +
" E.values();\n" +
" }\n" +
" };\n" +
"}" //$NON-NLS-1$
);
fullBuild();
expectingNoProblems();
}
public void testBuildLargeFile_01() throws JavaModelException, Exception {
IPath projectPath = env.addProject("Bug544921Test", "1.8"); //$NON-NLS-1$
scaffoldProject(projectPath, 1, 10, 64);
fullBuild();
expectingNoProblems();
}
public void testBuildLargeFile_02() throws JavaModelException, Exception {
IPath projectPath = env.addProject("Bug544921Test", "1.8"); //$NON-NLS-1$
scaffoldProject(projectPath, 2, 500, 64);
fullBuild();
expectingNoProblems();
}
public void testBuildLargeFile_03() throws JavaModelException, Exception {
IPath projectPath = env.addProject("Bug544921Test", "1.8"); //$NON-NLS-1$
scaffoldProject(projectPath, 3, 500, 64);
fullBuild();
expectingNoProblems();
}
private boolean hasEnoughMemory(long required) {
long bytes = Runtime.getRuntime().maxMemory();
long megabytes = bytes / 1024 / 1024;
return megabytes > required;
}
public void testBuildLargeFile_04() throws JavaModelException, Exception {
if (hasEnoughMemory(2048)) {
IPath projectPath = env.addProject("Bug544921Test", "1.8"); //$NON-NLS-1$
scaffoldProject(projectPath, 4, 500, 64);
fullBuild();
expectingNoProblems();
}
}
public void testBuildLargeFile_05() throws JavaModelException, Exception {
if (hasEnoughMemory(2048)) {
IPath projectPath = env.addProject("Bug544921Test", "1.8"); //$NON-NLS-1$
scaffoldProject(projectPath, 5, 500, 64);
fullBuild();
expectingNoProblems();
}
}
public void testBuildLargeFile_08() throws JavaModelException, Exception {
if (hasEnoughMemory(2048)) {
IPath projectPath = env.addProject("Bug544921Test", "1.8"); //$NON-NLS-1$
scaffoldProject(projectPath, 8, 500, 64);
fullBuild();
expectingNoProblems();
}
}
public void testBuildLargeFile_10() throws JavaModelException, Exception {
if (hasEnoughMemory(2048)) {
IPath projectPath = env.addProject("Bug544921Test", "1.8"); //$NON-NLS-1$
scaffoldProject(projectPath, 10, 500, 64);
fullBuild();
expectingNoProblems();
}
}
private void scaffoldProject(IPath projectPath, int maxPeripheral, int maxRegister, int maxFields) throws JavaModelException {
env.addExternalJars(projectPath, Util.getJavaClassLibs());
env.addClass(projectPath, "reg", "Field", //$NON-NLS-1$ //$NON-NLS-2$
"package reg;\n" +
"\n" +
"import reg.Register.AccessType;\n" +
"\n" +
"public class Field {\n" +
" String name;\n" +
" String description;\n" +
" long bitRange;\n" +
" AccessType accessType;\n" +
"\n" +
" public Field(String name, String description, long bitRange, AccessType accessType) {\n" +
" super();\n" +
" this.name = name;\n" +
" this.description = description;\n" +
" this.bitRange = bitRange;\n" +
" this.accessType = accessType;\n" +
" }\n" +
"\n" +
" @Override\n" +
" public String toString() {\n" +
" return \"Field [name=\" + name + \", description=\" + description + \", bitRange=\" + bitRange + \", accessType=\"\n" +
" + accessType + \"]\";\n" +
" }\n" +
" \n" +
"}" //$NON-NLS-1$
);
env.addClass(projectPath, "reg", "Peripheral", //$NON-NLS-1$ //$NON-NLS-2$
"package reg;\n" +
"\n" +
"import java.util.Collection;\n" +
"import java.util.Map;\n" +
"import java.util.TreeMap;\n" +
"\n" +
"public class Peripheral {\n" +
"\n" +
" String name;\n" +
" String version;\n" +
" String description;\n" +
" String groupName;\n" +
" long baseAddress;\n" +
" long size;\n" +
"\n" +
" Map<String, Register> registersMap;\n" +
"\n" +
" public Peripheral(String name, String version, String description, String groupName,\n" +
" long baseAddress, long size) {\n" +
" super();\n" +
" this.name = name;\n" +
" this.version = version;\n" +
" this.description = description;\n" +
" this.groupName = groupName;\n" +
" this.baseAddress = baseAddress;\n" +
" this.size = size;\n" +
" }\n" +
"\n" +
" private void initRegistersMap(){\n" +
" if (registersMap != null) {\n" +
" return;\n" +
" }\n" +
" registersMap = new TreeMap<>();\n" +
" for (java.lang.reflect.Field field : this.getClass().getDeclaredFields()) {\n" +
" if (!Register.class.isAssignableFrom(field.getType())){\n" +
" continue;\n" +
" }\n" +
" try {\n" +
" registersMap.put(field.getName(), (Register) field.get(this));\n" +
" } catch (Exception e) {\n" +
" e.printStackTrace();\n" +
" }\n" +
" }\n" +
" }\n" +
"\n" +
" public Register getRegister(String name) {\n" +
" return registersMap.get(name);\n" +
" }\n" +
" public Collection<Register> getRegisters(){\n" +
" initRegistersMap();\n" +
" return registersMap.values();\n" +
" }\n" +
"}\n" //$NON-NLS-1$
);
env.addClass(projectPath, "reg", "Reg", //$NON-NLS-1$ //$NON-NLS-2$
"package reg;\n" +
"\n" +
"public final class Reg {\n" +
"\n" +
" Peripheral_TIMER0 peripheral_Timer0 = new Peripheral_TIMER0();\n" +
"\n" +
" public static final class Peripheral_TIMER0 extends Peripheral {\n" +
"\n" +
" public Peripheral_TIMER0() {\n" +
" super(\"TIMER0\", \"1.0\", \"desc\", \"groupName\", 0, 32);\n" +
" }\n" +
"\n" +
" public Reg_CR regCR = new Reg_CR();\n" +
"\n" +
" public static final class Reg_CR extends Register {\n" +
" public Reg_CR() {\n" +
" super(\"CR\", \"\", 0, 32, AccessType.readWrite, 0xf, 0x0);\n" +
" }\n" +
"\n" +
" // fields of CR\n" +
" public Field_EN fieldEn = new Field_EN();\n" +
"\n" +
" public static final class Field_EN extends Field {\n" +
" public Field_EN() {\n" +
" super(\"EN\", \"description\", 0, AccessType.readWrite);\n" +
" }\n" +
" }\n" +
"\n" +
" public Field_RST fieldRST = new Field_RST();\n" +
"\n" +
" public static final class Field_RST extends Field {\n" +
" public Field_RST() {\n" +
" super(\"RST\", \"description\", 1, AccessType.readWrite);\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"\n" +
" public static void main(String[] args) {\n" +
" Reg reg = new Reg();\n" +
"\n" +
" System.out.println(reg.peripheral_Timer0.regCR.name + \": \" + reg.peripheral_Timer0.regCR.resetValue);\n" +
" System.out.println(reg.peripheral_Timer0.regCR.fieldEn.name + \": \" + reg.peripheral_Timer0.regCR.fieldEn.bitRange);\n" +
" }\n" +
"}\n" //$NON-NLS-1$
);
env.addClass(projectPath, "reg", "Register", //$NON-NLS-1$ //$NON-NLS-2$
"package reg;\n" +
"\n" +
"import java.util.Collection;\n" +
"import java.util.Map;\n" +
"import java.util.TreeMap;\n" +
"\n" +
"public class Register {\n" +
"\n" +
" public enum AccessType {\n" +
" readOnly, readWrite;\n" +
" }\n" +
"\n" +
" String name;\n" +
" String description;\n" +
" long addressOffset;\n" +
" long size;\n" +
" AccessType accessType;\n" +
" long resetValue;\n" +
" long resetMask;\n" +
" long value;\n" +
"\n" +
" Map<String, Field> fieldsMap;\n" +
"\n" +
" public Register(String name, String description, long addressOffset, long size,\n" +
" AccessType accessType, long resetValue, long resetMask) {\n" +
" this.name = name;\n" +
" this.description = description;\n" +
" this.addressOffset = addressOffset;\n" +
" this.size = size;\n" +
" this.accessType = accessType;\n" +
" this.resetValue = resetValue;\n" +
" this.resetMask = resetMask;\n" +
"\n" +
" }\n" +
"\n" +
" private void initFieldsMap(){\n" +
" if (fieldsMap != null) {\n" +
" return;\n" +
" }\n" +
" fieldsMap = new TreeMap<>();\n" +
" for (java.lang.reflect.Field field : this.getClass().getDeclaredFields()) {\n" +
" if (!Field.class.isAssignableFrom(field.getType())){\n" +
" continue;\n" +
" }\n" +
" try {\n" +
" fieldsMap.put(field.getName(), (Field) field.get(this));\n" +
" } catch (Exception e) {\n" +
" e.printStackTrace();\n" +
" }\n" +
" }\n" +
" }\n" +
"\n" +
" public void setValue(long value){\n" +
" this.value = value;\n" +
" }\n" +
"\n" +
" public long getValue(){\n" +
" return this.value;\n" +
" }\n" +
"\n" +
" public Collection<Field> getFields(){\n" +
" initFieldsMap();\n" +
" return fieldsMap.values();\n" +
" }\n" +
"\n" +
" @Override\n" +
" public String toString() {\n" +
" return \"Register [name=\" + name + \", description=\" + description + \", addressOffset=\" + addressOffset\n" +
" + \", size=\" + size + \", accessType=\" + accessType + \", resetValue=\" + resetValue + \", resetMask=\"\n" +
" + resetMask + \"]\";\n" +
" }\n" +
"\n" +
"\n" +
"}\n" //$NON-NLS-1$
);
env.addClass(projectPath, "reg.generate", "DeviceXY", genSource(maxPeripheral, maxRegister, maxFields));
}
public static String genSource(int maxPeripheral, int maxRegister, int maxFields) {
/*
*
* The example that took 25 minutes was generated with: int maxPeripheral = 10;
* int maxRegister = 500; int maxFields = 64;
*
* Still performs ok (less than a minute): int maxPeripheral = 2; int
* maxRegister = 500; int maxFields = 64;
*
* With this (8 MB) it gets already slow (few minutes): int maxPeripheral = 3;
* int maxRegister = 500; int maxFields = 64;
*
* This takes 5 minutes (14MB file-size): int maxPeripheral = 5; int maxRegister
* = 500; int maxFields = 64;
*/
StringBuilder source = new StringBuilder();
source.append("package reg.generate;").append(System.lineSeparator());
source.append("public class DeviceXY {").append(System.lineSeparator());
source.append("private static DeviceXY instance;").append(System.lineSeparator());
source.append("private DeviceXY() {}").append(System.lineSeparator());
source.append("public static DeviceXY getInstance() {").append(System.lineSeparator());
source.append(" if (instance == null) { instance = new DeviceXY(); }").append(System.lineSeparator());
source.append(" return instance;").append(System.lineSeparator());
source.append("}").append(System.lineSeparator());
for (int peripheral = 0; peripheral < maxPeripheral; peripheral++) {
String peripheralName = "peri_" + peripheral;
String peripheralClassName = String.valueOf(Character.toUpperCase(peripheralName.charAt(0)))
+ peripheralName.substring(1);
source.append("public ").append(peripheralClassName).append(" ").append(peripheralName)
.append(" = new ").append(peripheralClassName).append("();").append(System.lineSeparator());
source.append("public static final class ").append(peripheralClassName)
.append(" extends reg.Peripheral {").append(System.lineSeparator());
// constructor start
source.append("public ").append(peripheralClassName).append("() {").append(System.lineSeparator());
source.append(" super(\"").append(peripheralName).append("\",")
.append("\"1.0\",\"desc\", \"groupName\", 0, 32);").append(System.lineSeparator());
source.append("}").append(System.lineSeparator());
// constructor end
for (int register = 0; register < maxRegister; register++) {
String registerName = "reg_" + register;
String registerClassName = String.valueOf(Character.toUpperCase(registerName.charAt(0)))
+ registerName.substring(1);
source.append("public ").append(registerClassName).append(" ").append(registerName)
.append(" = new ").append(registerClassName).append("();").append(System.lineSeparator());
source.append("/**").append(System.lineSeparator());
source.append("* Register ").append(registerName).append(System.lineSeparator());
source.append("*/").append(System.lineSeparator());
source.append("public static final class ").append(registerClassName)
.append(" extends reg.Register {").append(System.lineSeparator());
// constructor start
source.append("public ").append(registerClassName).append("() {")
.append(System.lineSeparator());
source.append(" super(\"").append(registerName).append("\",")
.append("\"desc\", 0, 32, AccessType.readWrite, 0xf, 0x0);").append(System.lineSeparator());
source.append("}").append(System.lineSeparator());
// constructor end
source.append("//fields").append(System.lineSeparator());
for (int field = 0; field < maxFields; field++) {
String fieldName = "field_" + field;
source.append("public ").append("reg.Field").append(" ").append(fieldName)
.append(" = new ").append("reg.Field").append("(\"").append(fieldName).append("\",")
.append("\"desc\", 0, AccessType.readWrite);").append(System.lineSeparator());
}
source.append("}").append(System.lineSeparator());
}
source.append("}").append(System.lineSeparator());
}
source.append("}").append(System.lineSeparator());
return source.toString();
}
}