Skip to content

Commit

Permalink
update tests
Browse files Browse the repository at this point in the history
fix tests to not rely on removed python versions
  • Loading branch information
Seppli11 committed Nov 27, 2024
1 parent 1f7eea4 commit 566023b
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,7 @@
import org.sonar.plugins.python.api.PythonVersionUtils;
import org.sonar.python.checks.utils.PythonCheckVerifier;

import static org.assertj.core.api.Assertions.assertThat;

class PytzUsageCheckTest {
@Test
void test_38() {
ProjectPythonVersion.setCurrentVersions(EnumSet.of(PythonVersionUtils.Version.V_38));
var issues = PythonCheckVerifier.issues("src/test/resources/checks/pytzUsage.py", new PytzUsageCheck());
assertThat(issues)
.isEmpty();
}

@Test
void test_39_310_311_312() {
ProjectPythonVersion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ public static boolean isValidForProjectPythonVersion(List<String> validForPython
if (validForPythonVersions.isEmpty()) {
return true;
}
if(supportedPythonVersions == null) {
throw new IllegalStateException("supportedPythonVersion is uninitialized. Call builtinSymbols() first");
}
HashSet<String> intersection = new HashSet<>(validForPythonVersions);
intersection.retainAll(supportedPythonVersions);
return !intersection.isEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.protobuf.TextFormat;
import java.util.Collections;
import java.util.HashSet;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.sonar.plugins.python.api.symbols.AmbiguousSymbol;
import org.sonar.plugins.python.api.symbols.ClassSymbol;
Expand All @@ -36,6 +37,10 @@
import static org.sonar.python.PythonTestUtils.parse;

class ClassSymbolImplTest {
@BeforeEach
void setup() {
TypeShed.resetBuiltinSymbols();
}

@Test
void hasUnresolvedTypeHierarchy() {
Expand Down Expand Up @@ -315,12 +320,12 @@ void overloaded_methods() throws TextFormat.ParseException {
"methods {\n" +
" name: \"foo\"\n" +
" fully_qualified_name: \"mod.A.foo\"\n" +
" valid_for: \"36\"\n" +
" valid_for: \"39\"\n" +
"}\n" +
"overloaded_methods {\n" +
" name: \"foo\"\n" +
" fullname: \"mod.A.foo\"\n" +
" valid_for: \"39\"\n" +
" valid_for: \"310\"\n" +
" definitions {\n" +
" name: \"foo\"\n" +
" fully_qualified_name: \"mod.A.foo\"\n" +
Expand All @@ -334,7 +339,7 @@ void overloaded_methods() throws TextFormat.ParseException {
ClassSymbolImpl classSymbol = new ClassSymbolImpl(classSymbol(protobuf), "mod");
Symbol foo = classSymbol.resolveMember("foo").get();
assertThat(foo.is(Symbol.Kind.AMBIGUOUS)).isTrue();
assertThat(((SymbolImpl) foo).validForPythonVersions()).containsExactlyInAnyOrder("36", "39");
assertThat(((SymbolImpl) foo).validForPythonVersions()).containsExactlyInAnyOrder("39", "310");
}

private static SymbolsProtos.ClassSymbol classSymbol(String protobuf) throws TextFormat.ParseException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,16 +273,15 @@ void importing_stdlib() {
FunctionDef functionDef = functionTreesByName.get("importing_stdlib");
Map<String, Symbol> symbolByName = getSymbolByName(functionDef);

assertThat(symbolByName.keySet()).containsOnly("math");
assertThat(symbolByName.get("math").usages()).extracting(Usage::kind).containsExactly(Usage.Kind.IMPORT, Usage.Kind.OTHER);
assertThat(symbolByName.keySet()).containsOnly("os");
assertThat(symbolByName.get("os").usages()).extracting(Usage::kind).containsExactly(Usage.Kind.IMPORT, Usage.Kind.OTHER);

CallExpression callExpression = (CallExpression) ((ExpressionStatement) functionDef.body().statements().get(1)).expressions().get(0);
Symbol qualifiedExpressionSymbol = callExpression.calleeSymbol();
assertThat(qualifiedExpressionSymbol).isNotNull();
assertThat(qualifiedExpressionSymbol.kind()).isEqualTo(Symbol.Kind.AMBIGUOUS);
Symbol symbol = ((AmbiguousSymbolImpl) qualifiedExpressionSymbol).alternatives().iterator().next();
assertThat(symbol.kind()).isEqualTo(Symbol.Kind.FUNCTION);
assertThat(((FunctionSymbolImpl)symbol).declaredReturnType().canOnlyBe("float")).isTrue();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2646,48 +2646,49 @@ void unary_expression_of_variables_with_try_except(String code, PythonType expec
@Test
void imported_ambiguous_symbol() {
FileInput fileInput = inferTypes("""
from math import acos, atan
acos
atan
""");
UnionType acosType = (UnionType) ((ExpressionStatement) fileInput.statements().statements().get(1)).expressions().get(0).typeV2();
assertThat(acosType.candidates()).allMatch(p -> p instanceof FunctionType);
assertThat(acosType.candidates()).extracting(PythonType::name).containsExactly("acos", "acos");
assertThat(acosType.candidates()).map(FunctionType.class::cast).extracting(FunctionType::returnType).extracting(PythonType::unwrappedType).containsExactly(FLOAT_TYPE,
FLOAT_TYPE);

UnionType atanType = (UnionType) ((ExpressionStatement) fileInput.statements().statements().get(2)).expressions().get(0).typeV2();
assertThat(atanType.candidates()).allMatch(p -> p instanceof FunctionType);
assertThat(atanType.candidates()).extracting(PythonType::name).containsExactly("atan", "atan");
assertThat(atanType.candidates()).map(FunctionType.class::cast).extracting(FunctionType::returnType).extracting(PythonType::unwrappedType).containsExactly(FLOAT_TYPE,
FLOAT_TYPE);
from os.path import realpath
realpath
""");
UnionType realpathType = (UnionType) ((ExpressionStatement) fileInput.statements().statements().get(1)).expressions().get(0).typeV2();
assertThat(realpathType.candidates()).allMatch(p -> p instanceof FunctionType);
assertThat(realpathType.candidates()).extracting(PythonType::name).containsExactly("realpath", "realpath", "realpath", "realpath");
assertThat(realpathType.candidates())
.map(FunctionType.class::cast)
.extracting(FunctionType::returnType)
.extracting(PythonType::unwrappedType)
.containsExactly(PythonType.UNKNOWN, PythonType.UNKNOWN, PythonType.UNKNOWN, PythonType.UNKNOWN);
}

@Test
void imported_ambiguous_symbol_try_except() {
FileInput fileInput = inferTypes("""
try:
from math import acos
acos
from os.path import realpath
realpath
except:
...
acos
realpath
""");
Expression acosExpr1 = TreeUtils.firstChild(fileInput.statements().statements().get(0), ExpressionStatement.class::isInstance)
.map(ExpressionStatement.class::cast)
.map(ExpressionStatement::expressions)
.map(expressions -> expressions.get(0))
.map(Expression.class::cast)
.get();
UnionType acosType1 = (UnionType) acosExpr1.typeV2();
assertThat(acosType1.candidates()).allMatch(p -> p instanceof FunctionType);
assertThat(acosType1.candidates()).map(FunctionType.class::cast).extracting(FunctionType::returnType).extracting(PythonType::unwrappedType).containsExactly(FLOAT_TYPE,
FLOAT_TYPE);
assertThat(acosType1.candidates())
.map(FunctionType.class::cast)
.extracting(FunctionType::returnType)
.extracting(PythonType::unwrappedType)
.containsExactly(PythonType.UNKNOWN, PythonType.UNKNOWN, PythonType.UNKNOWN, PythonType.UNKNOWN);

UnionType acosType2 = (UnionType) ((ExpressionStatement) fileInput.statements().statements().get(1)).expressions().get(0).typeV2();
assertThat(acosType2.candidates()).allMatch(p -> p instanceof FunctionType);
assertThat(acosType2.candidates()).map(FunctionType.class::cast).extracting(FunctionType::returnType).extracting(PythonType::unwrappedType).containsExactly(FLOAT_TYPE,
FLOAT_TYPE);
assertThat(acosType2.candidates())
.map(FunctionType.class::cast)
.extracting(FunctionType::returnType)
.extracting(PythonType::unwrappedType)
.containsExactly(PythonType.UNKNOWN, PythonType.UNKNOWN, PythonType.UNKNOWN, PythonType.UNKNOWN);
}

@Test
Expand Down Expand Up @@ -2971,18 +2972,18 @@ def lock():
void basic_imported_symbols() {
FileInput fileInput = inferTypes(
"""
import fcntl, math
import fcntl, os.path
fcntl
math
os.path
"""
);
PythonType fnctlModule = ((ExpressionStatement) fileInput.statements().statements().get(1)).expressions().get(0).typeV2();
assertThat(fnctlModule).isInstanceOf(ModuleType.class);
assertThat(fnctlModule.name()).isEqualTo("fcntl");
PythonType mathModule = ((ExpressionStatement) fileInput.statements().statements().get(2)).expressions().get(0).typeV2();
assertThat(mathModule).isInstanceOf(ModuleType.class);
assertThat(mathModule.name()).isEqualTo("math");
assertThat(((UnionType) mathModule.resolveMember("acos").get()).candidates()).allMatch(FunctionType.class::isInstance);
PythonType osPathModule = ((ExpressionStatement) fileInput.statements().statements().get(2)).expressions().get(0).typeV2();
assertThat(osPathModule).isInstanceOf(ModuleType.class);
assertThat(osPathModule.name()).isEqualTo("path");
assertThat(((UnionType) osPathModule.resolveMember("realpath").get()).candidates()).allMatch(FunctionType.class::isInstance);
}

// TODO SONARPY-2176 ProjectLevelSymbolTable#getType should be able to resolve types when there is a conflict between a member and a subpackage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ void builtin312DescriptorsTest() {
void builtinFloatDisambiguation() {
var provider = typeshedDescriptorsProvider();
var builtinDescriptors = provider.builtinDescriptors();
var floatDescriptor = builtinDescriptors.get("float");
var floatDescriptor = builtinDescriptors.get("int");
assertThat(floatDescriptor.kind()).isEqualTo(Descriptor.Kind.CLASS);
var newMember = ((ClassDescriptor) floatDescriptor).members().stream().filter(m -> m.name().equals("__new__")).findFirst().get();
var newMember = ((ClassDescriptor) floatDescriptor).members().stream().filter(m -> m.name().equals("to_bytes")).findFirst().get();
assertThat(newMember.kind()).isEqualTo(Descriptor.Kind.AMBIGUOUS);
assertThat(((AmbiguousDescriptor) newMember).alternatives()).hasSize(2);
}
Expand All @@ -79,9 +79,9 @@ void builtinFloatDisambiguation() {
void builtinFloatNoDisambiguation() {
var provider = new TypeShedDescriptorsProvider(Set.of(), Set.of(PythonVersionUtils.Version.V_312));
var builtinDescriptors = provider.builtinDescriptors();
var floatDescriptor = builtinDescriptors.get("float");
var floatDescriptor = builtinDescriptors.get("int");
assertThat(floatDescriptor.kind()).isEqualTo(Descriptor.Kind.CLASS);
var newMember = ((ClassDescriptor) floatDescriptor).members().stream().filter(m -> m.name().equals("__new__")).findFirst().get();
var newMember = ((ClassDescriptor) floatDescriptor).members().stream().filter(m -> m.name().equals("to_bytes")).findFirst().get();
assertThat(newMember.kind()).isEqualTo(Descriptor.Kind.FUNCTION);
}

Expand Down Expand Up @@ -111,13 +111,13 @@ void cacheTest() {
@Test
void stdlibDescriptors() {
var provider = typeshedDescriptorsProvider();
var mathDescriptors = provider.descriptorsForModule("math");
var descriptor = mathDescriptors.get("acos");
var osPathDescriptor = provider.descriptorsForModule("os.path");
var descriptor = osPathDescriptor.get("realpath");
assertThat(descriptor.kind()).isEqualTo(Descriptor.Kind.AMBIGUOUS);
var acosDescriptor = ((AmbiguousDescriptor) descriptor).alternatives().iterator().next();
assertThat(acosDescriptor.kind()).isEqualTo(Descriptor.Kind.FUNCTION);
assertThat(((FunctionDescriptor) acosDescriptor).parameters()).hasSize(1);
assertThat(((FunctionDescriptor) acosDescriptor).annotatedReturnTypeName()).isEqualTo("float");
var realPathDescriptor = ((AmbiguousDescriptor) descriptor).alternatives().iterator().next();
assertThat(realPathDescriptor.kind()).isEqualTo(Descriptor.Kind.FUNCTION);
assertThat(((FunctionDescriptor) realPathDescriptor).parameters()).hasSizeBetween(1, 2);
assertThat(((FunctionDescriptor) realPathDescriptor).annotatedReturnTypeName()).isNull();

var threadingSymbols = provider.descriptorsForModule("threading");
assertThat(threadingSymbols.get("Thread").kind()).isEqualTo(Descriptor.Kind.CLASS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,6 @@ void str() {
assertThat(strClass.resolveMember("removeprefix")).isNotEmpty();
assertThat(strClass.resolveMember("removesuffix")).isNotEmpty();

setPythonVersions(PythonVersionUtils.fromString("3.8"));
strClass = TypeShed.typeShedClass("str");
assertThat(strClass.superClasses()).extracting(Symbol::kind, Symbol::name).containsExactlyInAnyOrder(tuple(Kind.CLASS, "Sequence"));
assertThat(strClass.resolveMember("removeprefix")).isEmpty();
assertThat(strClass.resolveMember("removesuffix")).isEmpty();

setPythonVersions(PythonVersionUtils.allVersions());
}

Expand Down Expand Up @@ -120,14 +114,15 @@ void typing_module() {

@Test
void stdlib_symbols() {
Map<String, Symbol> mathSymbols = symbolsForModule("math");
Symbol symbol = mathSymbols.get("acos");
Map<String, Symbol> mathSymbols = symbolsForModule("os.path");
Symbol symbol = mathSymbols.get("realpath");
assertThat(symbol.kind()).isEqualTo(Symbol.Kind.AMBIGUOUS);
Symbol acosSymbol = ((AmbiguousSymbolImpl) symbol).alternatives().iterator().next();
assertThat(acosSymbol.kind()).isEqualTo(Kind.FUNCTION);
assertThat(((FunctionSymbolImpl) acosSymbol).parameters()).hasSize(1);
assertThat(((FunctionSymbolImpl) acosSymbol).declaredReturnType().canOnlyBe("float")).isTrue();
assertThat(TypeShed.symbolWithFQN("math", "math.acos")).isSameAs(symbol);
FunctionSymbolImpl acosFunctionsymbol = (FunctionSymbolImpl) acosSymbol;
assertThat(acosFunctionsymbol.parameters()).hasSizeBetween(1, 2);
assertThat(acosFunctionsymbol.declaredReturnType()).isInstanceOf(AnyType.class);
assertThat(TypeShed.symbolWithFQN("os.path", "os.path.realpath")).isSameAs(symbol);
assertThat(mathSymbols.values()).allMatch(s -> s.usages().isEmpty());

Map<String, Symbol> threadingSymbols = symbolsForModule("threading");
Expand Down Expand Up @@ -450,7 +445,7 @@ void function_symbols_from_protobuf() throws TextFormat.ParseException {
@Test
void pythonVersions() {
Symbol range = TypeShed.builtinSymbols().get("range");
assertThat(((SymbolImpl) range).validForPythonVersions()).containsExactlyInAnyOrder( "36", "37", "38", "39", "310", "311");
assertThat(((SymbolImpl) range).validForPythonVersions()).containsExactlyInAnyOrder( "39", "310", "311", "312", "313");
assertThat(range.kind()).isEqualTo(Kind.CLASS);

// python 2
Expand All @@ -462,7 +457,7 @@ void pythonVersions() {
// python 3
setPythonVersions(PythonVersionUtils.fromString("3.8"));
range = TypeShed.builtinSymbols().get("range");
assertThat(((SymbolImpl) range).validForPythonVersions()).containsExactlyInAnyOrder("36", "37", "38", "39", "310", "311");
assertThat(((SymbolImpl) range).validForPythonVersions()).containsExactlyInAnyOrder("39", "310", "311", "312", "313");
assertThat(range.kind()).isEqualTo(Kind.CLASS);

setPythonVersions(PythonVersionUtils.fromString("3.10"));
Expand Down
4 changes: 2 additions & 2 deletions python-frontend/src/test/resources/semantic/symbols2.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ def assignment_expression_in_dict_comprehension():
something(last)

def importing_stdlib():
import math
math.acos(0)
import os.path
os.path.realpath("")


def importing_submodule():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,12 @@ void test_python_version_parameter() {

PythonInputFile inputFile = inputFile(FILE_1);
activeRules = new ActiveRulesBuilder().build();
context.setSettings(new MapSettings().setProperty("sonar.python.version", "3.8"));
context.setSettings(new MapSettings().setProperty("sonar.python.version", "3.13"));
PythonIndexer pythonIndexer = pythonIndexer(List.of(inputFile));

sensor(pythonIndexer).execute(context);

assertThat(ProjectPythonVersion.currentVersions()).containsExactly(PythonVersionUtils.Version.V_38);
assertThat(ProjectPythonVersion.currentVersions()).containsExactly(PythonVersionUtils.Version.V_313);
}

private IPynbSensor notebookSensor() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -680,9 +680,9 @@ void test_python_version_parameter_no_warning() {

activeRules = new ActiveRulesBuilder().build();

context.setSettings(new MapSettings().setProperty("sonar.python.version", "3.8"));
context.setSettings(new MapSettings().setProperty("sonar.python.version", "3.13"));
sensor().execute(context);
assertThat(ProjectPythonVersion.currentVersions()).containsExactly(PythonVersionUtils.Version.V_38);
assertThat(ProjectPythonVersion.currentVersions()).containsExactly(PythonVersionUtils.Version.V_313);
assertThat(logTester.logs(Level.WARN)).doesNotContain(PythonSensor.UNSET_VERSION_WARNING);
verify(analysisWarning, times(0)).addUnique(PythonSensor.UNSET_VERSION_WARNING);
}
Expand Down

0 comments on commit 566023b

Please sign in to comment.