<commit_before>/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    <NAME> (<EMAIL>) - initial API and implementation

*******************************************************************************/

package org.eclipse.imp.pdb.test;

import junit.framework.TestCase;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IMap;
import org.eclipse.imp.pdb.facts.IMapWriter;
import org.eclipse.imp.pdb.facts.INode;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.IValueFactory;
import org.eclipse.imp.pdb.facts.exceptions.FactTypeUseException;
import org.eclipse.imp.pdb.facts.exceptions.FactTypeDeclarationException;
import org.eclipse.imp.pdb.facts.type.Type;
import org.eclipse.imp.pdb.facts.type.TypeFactory;
import org.eclipse.imp.pdb.facts.type.TypeStore;

public abstract class BaseTestAnnotations extends TestCase {
    private IValueFactory vf;
    private TypeFactory tf = TypeFactory.getInstance();
    private TypeStore ts = new TypeStore();
    private Type E;
    private Type N;
    
	protected void setUp(IValueFactory factory) throws Exception {
		super.setUp();
		vf = factory;
		E = tf.abstractDataType(ts, "E");
		N = tf.constructor(ts, E, "n", tf.integerType());
		ts.declareAnnotation(E, "x", tf.integerType());
	}
	
	public void testDeclarationOnNonAllowedType() {
		try {
			ts.declareAnnotation(tf.integerType(), "a", tf.integerType());
		}
		catch (FactTypeDeclarationException e) {
			// this should happen
		}
		try {
			ts.declareAnnotation(tf.realType(), "a", tf.integerType());
		}
		catch (FactTypeDeclarationException e) {
			// this should happen
		}
	}
	
	public void testDoubleDeclaration() {
		try {
			ts.declareAnnotation(E, "size", tf.integerType());
		}
		catch (FactTypeDeclarationException | FactTypeUseException e) {
			fail(e.toString());
		}

        try {
			ts.declareAnnotation(E, "size", tf.realType());
			fail("double declaration is not allowed");
		}
		catch (FactTypeDeclarationException e) {
			// this should happen
		}
	}
	
	public void testSetAnnotation() {
		IConstructor n = vf.constructor(N, vf.integer(0));
		ts.declareAnnotation(E, "size", tf.integerType());
		
		try {
			n.asAnnotatable().setAnnotation("size", vf.integer(0));
		}
		catch (FactTypeDeclarationException | FactTypeUseException e) {
			fail(e.toString());
		}
    }
	
	public void testGetAnnotation() {
		IConstructor n = vf.constructor(N, vf.integer(0));
		ts.declareAnnotation(E, "size", tf.integerType());
		
		try {
			if (n.asAnnotatable().getAnnotation("size") != null) {
				fail("annotation should be null");
			}
		} catch (FactTypeUseException e) {
			fail(e.toString());
		}
		
		IConstructor m = n.asAnnotatable().setAnnotation("size", vf.integer(1));
		IValue b = m.asAnnotatable().getAnnotation("size");
		if (!b.isEqual(vf.integer(1))) {
			fail();
		}
	}
	
	public void testImmutability() {
		IConstructor n = vf.constructor(N, vf.integer(0));
		ts.declareAnnotation(E, "size", tf.integerType());
		
		IConstructor m = n.asAnnotatable().setAnnotation("size", vf.integer(1));
		
		if (m == n) {
			fail("annotation setting should change object identity");
		}
		
		assertTrue(m.isEqual(n));
	}
	
	public void testDeclaresAnnotation() {
		IConstructor n = vf.constructor(N,  vf.integer(0));
		ts.declareAnnotation(E, "size", tf.integerType());
		
		if (!n.declaresAnnotation(ts, "size")) {
			fail();
		}
		
		if (n.declaresAnnotation(ts, "size2")) {
			fail();
		}
	}
	
	public void testEqualityNode() {
		final INode n = vf.node("hello");
		final INode na = n.asAnnotatable().setAnnotation("audience", vf.string("world"));		
	
		assertEqualityOfValueWithAndWithoutAnnotations(n, na);
	}
	
	public void testEqualityConstructor() {
		final IConstructor n = vf.constructor(N, vf.integer(1));
		final IConstructor na = n.asAnnotatable().setAnnotation("x", vf.integer(1));
			
		assertEqualityOfValueWithAndWithoutAnnotations(n, na);
	}
	
	public void assertEqualityOfValueWithAndWithoutAnnotations(IValue n, IValue na) {
				
		assertIsEqualButNotEquals(n, na);
		
		assertIsEqualButNotEquals(vf.set(n), vf.set(na));
		assertIsEqualButNotEquals(vf.set(vf.set(n)), vf.set(vf.set(na)));
				
		assertIsEqualButNotEquals(vf.list(n), vf.list(na));
		assertIsEqualButNotEquals(vf.list(vf.list(n)), vf.list(vf.list(na)));
					
		// check: with keys
		{
			final IMap mapN = createMap(n, vf.integer(1));
			final IMap mapNA = createMap(na, vf.integer(1));
			final IMap mapMapN = createMap(mapN, vf.integer(1));
			final IMap mapMapNA = createMap(mapNA, vf.integer(1));

			assertIsEqualButNotEquals(mapN, mapNA);
			assertIsEqualButNotEquals(mapMapN, mapMapNA);
		}
		
		// check: with values
		{
			final IMap mapN = createMap(vf.integer(1), n);
			final IMap mapNA = createMap(vf.integer(1), na);
			final IMap mapMapN = createMap(vf.integer(1), mapN);
			final IMap mapMapNA = createMap(vf.integer(1), mapNA);

			assertIsEqualButNotEquals(mapN, mapNA);
			assertIsEqualButNotEquals(mapMapN, mapMapNA);
		}

	}

	/**
	 * Create a @IMap from a variable argument list.
	 * 
	 * @param keyValuePairs
	 *            a sequence of alternating keys and values
	 * @return an new @IMap instance
	 */
	public IMap createMap(IValue... keyValuePairs) {
		assert (keyValuePairs.length % 2 == 0);

		IMapWriter w = vf.mapWriter();

		for (int i = 0; i < keyValuePairs.length / 2; i++) {
			w.put(keyValuePairs[i], keyValuePairs[i+1]);
		}<commit_msg>Add nesting inside of node and constructor to test case.<commit_after>/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    <NAME> (<EMAIL>) - initial API and implementation

*******************************************************************************/

package org.eclipse.imp.pdb.test;

import junit.framework.TestCase;

import org.eclipse.imp.pdb.facts.IConstructor;
import org.eclipse.imp.pdb.facts.IMap;
import org.eclipse.imp.pdb.facts.IMapWriter;
import org.eclipse.imp.pdb.facts.INode;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.IValueFactory;
import org.eclipse.imp.pdb.facts.exceptions.FactTypeUseException;
import org.eclipse.imp.pdb.facts.exceptions.FactTypeDeclarationException;
import org.eclipse.imp.pdb.facts.type.Type;
import org.eclipse.imp.pdb.facts.type.TypeFactory;
import org.eclipse.imp.pdb.facts.type.TypeStore;

public abstract class BaseTestAnnotations extends TestCase {
    private IValueFactory vf;
    private TypeFactory tf = TypeFactory.getInstance();
    private TypeStore ts = new TypeStore();
    private Type E;
    private Type N;
    
	protected void setUp(IValueFactory factory) throws Exception {
		super.setUp();
		vf = factory;
		E = tf.abstractDataType(ts, "E");
		N = tf.constructor(ts, E, "n", tf.integerType());
		ts.declareAnnotation(E, "x", tf.integerType());
	}
	
	public void testDeclarationOnNonAllowedType() {
		try {
			ts.declareAnnotation(tf.integerType(), "a", tf.integerType());
		}
		catch (FactTypeDeclarationException e) {
			// this should happen
		}
		try {
			ts.declareAnnotation(tf.realType(), "a", tf.integerType());
		}
		catch (FactTypeDeclarationException e) {
			// this should happen
		}
	}
	
	public void testDoubleDeclaration() {
		try {
			ts.declareAnnotation(E, "size", tf.integerType());
		}
		catch (FactTypeDeclarationException | FactTypeUseException e) {
			fail(e.toString());
		}

        try {
			ts.declareAnnotation(E, "size", tf.realType());
			fail("double declaration is not allowed");
		}
		catch (FactTypeDeclarationException e) {
			// this should happen
		}
	}
	
	public void testSetAnnotation() {
		IConstructor n = vf.constructor(N, vf.integer(0));
		ts.declareAnnotation(E, "size", tf.integerType());
		
		try {
			n.asAnnotatable().setAnnotation("size", vf.integer(0));
		}
		catch (FactTypeDeclarationException | FactTypeUseException e) {
			fail(e.toString());
		}
    }
	
	public void testGetAnnotation() {
		IConstructor n = vf.constructor(N, vf.integer(0));
		ts.declareAnnotation(E, "size", tf.integerType());
		
		try {
			if (n.asAnnotatable().getAnnotation("size") != null) {
				fail("annotation should be null");
			}
		} catch (FactTypeUseException e) {
			fail(e.toString());
		}
		
		IConstructor m = n.asAnnotatable().setAnnotation("size", vf.integer(1));
		IValue b = m.asAnnotatable().getAnnotation("size");
		if (!b.isEqual(vf.integer(1))) {
			fail();
		}
	}
	
	public void testImmutability() {
		IConstructor n = vf.constructor(N, vf.integer(0));
		ts.declareAnnotation(E, "size", tf.integerType());
		
		IConstructor m = n.asAnnotatable().setAnnotation("size", vf.integer(1));
		
		if (m == n) {
			fail("annotation setting should change object identity");
		}
		
		assertTrue(m.isEqual(n));
	}
	
	public void testDeclaresAnnotation() {
		IConstructor n = vf.constructor(N,  vf.integer(0));
		ts.declareAnnotation(E, "size", tf.integerType());
		
		if (!n.declaresAnnotation(ts, "size")) {
			fail();
		}
		
		if (n.declaresAnnotation(ts, "size2")) {
			fail();
		}
	}
	
	public void testEqualityNode() {
		final INode n = vf.node("hello");
		final INode na = n.asAnnotatable().setAnnotation("audience", vf.string("world"));		
	
		assertEqualityOfValueWithAndWithoutAnnotations(n, na);
	}
	
	public void testEqualityConstructor() {
		final IConstructor n = vf.constructor(N, vf.integer(1));
		final IConstructor na = n.asAnnotatable().setAnnotation("x", vf.integer(1));
			
		assertEqualityOfValueWithAndWithoutAnnotations(n, na);
	}
	
	public void assertEqualityOfValueWithAndWithoutAnnotations(IValue n, IValue na) {
				
		assertIsEqualButNotEquals(n, na);
		
		assertIsEqualButNotEquals(vf.set(n), vf.set(na));
		assertIsEqualButNotEquals(vf.set(vf.set(n)), vf.set(vf.set(na)));
				
		assertIsEqualButNotEquals(vf.list(n), vf.list(na));
		assertIsEqualButNotEquals(vf.list(vf.list(n)), vf.list(vf.list(na)));
					
		// check: with keys
		{
			final IMap mapN = createMap(n, vf.integer(1));
			final IMap mapNA = createMap(na, vf.integer(1));
			final IMap mapMapN = createMap(mapN, vf.integer(1));
			final IMap mapMapNA = createMap(mapNA, vf.integer(1));

			assertIsEqualButNotEquals(mapN, mapNA);
			assertIsEqualButNotEquals(mapMapN, mapMapNA);
		}
		
		// check: with values
		{
			final IMap mapN = createMap(vf.integer(1), n);
			final IMap mapNA = createMap(vf.integer(1), na);
			final IMap mapMapN = createMap(vf.integer(1), mapN);
			final IMap mapMapNA = createMap(vf.integer(1), mapNA);

			assertIsEqualButNotEquals(mapN, mapNA);
			assertIsEqualButNotEquals(mapMapN, mapMapNA);
		}

		assertIsEqualButNotEquals(vf.node("nestingInNode", n), vf.node("nestingInNode", na));
		
		final TypeStore ts = new TypeStore();
		final Type adtType = tf.abstractDataType(ts, "adtTypeNameThatIsIgnored", tf.valueType());
		final Type constructorType = tf.constructor(ts, adtType, "nestingInConstructor", tf.valueType());

		assertIsEqualButNotEquals(vf.constructor(constructorType, n), vf.constructor(constructorType, na));
	}

	/**
	 * Create a @IMap from a variable argument list.
	 * 
	 * @param keyValuePairs
	 *            a sequence of alternating keys and values
	 * @return an new @IMap instance
	 */
	public IMap createMap(IValue... keyValuePairs) {
		assert (keyValuePairs.length % 2 == 0);

		IMapWriter w = vf.mapWriter();

		for (int i = 0; i < keyValuePairs.length / 2; i++) {
			w.put(keyValuePairs[i], keyValuePairs[i+1]);
		}
{'fraction_non_alphanumeric': 0.1624822754191342, 'fraction_numerical': 0.005338226707815498, 'mean_word_length': 4.295936395759718, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5136356', 'n_tokens_mistral': 4399, 'n_tokens_neox': 3880, 'n_words': 829}