1/*
2 * Copyright (c) 2023 - 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16function main() {
17    testLocalIdentifier()
18    testArgument()
19    testCallExpression()
20    testNPE()
21    testFieldAccess()
22    testFieldAccess2()
23}
24
25function typeOf(i : Int) : int {
26    return 1;
27}
28
29function typeOf(o : Object) : int {
30    return -1;
31}
32
33function dummy(): Int | null {
34    return 5;
35}
36
37function testLocalIdentifier() : void {
38    let a : Int | null = dummy();
39    let b = a!;
40
41    assert typeOf(b) == 1: "b must be type Int";
42    assert b == 5 : "b must be 5";
43
44    let c = b + a! * 7;
45
46    assert c == 40: "c should be 40";
47
48    assert a! == (a)!;
49}
50
51function bar(arg : Int | null) : Int {
52    return arg!;
53}
54
55function testArgument() : void {
56    let a : Int | null = 7;
57    let b = bar(a);
58
59    assert typeOf(b) == 1: "b must be type Int";
60    assert b == 7;
61}
62
63function foo() : Double | null {
64    return new Double(3.1415);
65}
66
67class Foo {
68    foo() : Float | null {
69        return Float.DELTA;
70    }
71}
72
73function testCallExpression() {
74    let d = foo()!
75
76    assert d instanceof Double : "d must be type Double"
77    assert d == 3.1415 : "d must be 3.1415"
78
79    let sd = foo()!.toString()
80
81    assert "3.1415".equals(sd) : "s must be '3.1415'"
82
83    let f = new Foo().foo()!
84
85    assert f instanceof Float : "f must be type Float"
86    assert f == Float.DELTA : "f must be Float.DELTA"
87}
88
89function baz() : Byte | null {
90    return null;
91}
92
93function aux(): Object | null {
94   return null;
95}
96
97function testNPE() : void {
98    let o : Object | null = aux();
99    let npe_caught = false;
100
101    try {
102        (o as Object | null)!;
103        assert false : "this must not be executed";
104    } catch (ex: NullPointerError) {
105        npe_caught = true;
106    }
107
108    assert npe_caught : "NPE must be caught";
109
110    try {
111        baz()!;
112        assert false : "this must not be executed";
113    } catch (ex: NullPointerError) {
114        npe_caught = true;
115    }
116
117    assert npe_caught : "NPE must be caught";
118}
119
120class A {
121    public static c : Char | null = c'C';
122}
123
124class B {
125    public a : A | null;
126
127    constructor(a : A | null) {
128        this.a = a;
129    }
130
131    public setA(a : A) {
132        this.a = a;
133    }
134
135    public getA() : A {
136        return this.a!;
137    }
138}
139
140function testFieldAccess() : void {
141    let ac = A.c!;
142    assert ac == c'C' : "ac should be 'C'";
143
144    let a_orig = new A();
145    let b = new B(a_orig);
146
147    let a = b.a!;
148
149    assert a == a_orig : "a should be the object referenced by a_orig";
150
151    let c = b.a!.c!;
152
153    assert c == c'C' : "c should be 'C'";
154}
155
156function testFieldAccess2() : void {
157    let a = new A();
158    let b = new B(a);
159
160    assert b.getA() == a : "getA should return the same object that was given to the constructor";
161
162    let a2 = new A();
163    b.setA(a2);
164
165    assert b.getA() == a2 : "getA should return the same object that was given to setA";
166}
167