iconStore = $this->app->make(IconStoreService::class); } #[Test] public function test_get_returns_icon_content() { Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); $content = $this->iconStore->get(OtpTestData::ICON_PNG); $this->assertSame(OtpTestData::ICON_PNG_DATA, base64_encode($content)); } #[Test] public function test_get_returns_null_when_icon_is_missing() { $this->assertNull($this->iconStore->get(OtpTestData::ICON_PNG)); } #[Test] public function test_get_returns_content_when_icon_is_missing_on_disk_but_exists_in_db() { Settings::set('storeIconsInDatabase', true); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); $content = $this->iconStore->get(OtpTestData::ICON_PNG); $this->assertSame(OtpTestData::ICON_PNG_DATA, base64_encode($content)); } #[Test] public function test_get_returns_null_when_nothing_is_requested() { $this->assertNull($this->iconStore->get('')); } #[Test] #[DataProvider('supportedMimeTypesProvider')] public function test_mimeType_returns_correct_mimetype($name, $base64content, $expected) { Storage::disk('icons')->put($name, $base64content); $mimeType = $this->iconStore->mimeType($name); $this->assertStringContainsStringIgnoringCase($mimeType, $expected); } /** * Provide data for index tests */ public static function supportedMimeTypesProvider() { return [ 'PNG' => [ OtpTestData::ICON_PNG, OtpTestData::ICON_PNG_DATA, 'image/png', ], 'JPEG' => [ OtpTestData::ICON_JPEG, OtpTestData::ICON_JPEG_DATA, 'image/jpeg', ], 'WEBP' => [ OtpTestData::ICON_WEBP, OtpTestData::ICON_WEBP_DATA, 'image/webp', ], 'BPM' => [ OtpTestData::ICON_BMP, OtpTestData::ICON_BMP_DATA, 'image/bmp|image/x-ms-bmp', ], 'SVG' => [ OtpTestData::ICON_SVG, OtpTestData::ICON_SVG_DATA_ENCODED, 'image/svg+xml', ], ]; } #[Test] public function test_mimeType_returns_correct_mimetype_of_fake_icon() { Storage::disk('icons')->put(OtpTestData::ICON_JPEG, base64_decode(OtpTestData::ICON_PNG_DATA)); $mimeType = $this->iconStore->mimeType(OtpTestData::ICON_JPEG); $this->assertSame('image/png', $mimeType); } #[Test] public function test_mimeType_returns_null_when_icon_is_missing() { $this->assertFalse($this->iconStore->mimeType(OtpTestData::ICON_PNG)); } #[Test] public function test_mimeType_returns_null_when_nothing_is_requested() { $this->assertFalse($this->iconStore->mimeType('')); } #[Test] public function test_clear_deletes_all_icons_and_returns_true() { Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_JPEG, base64_decode(OtpTestData::ICON_JPEG_DATA)); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); $result = $this->iconStore->clear(); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); Storage::disk('icons')->assertMissing(OtpTestData::ICON_JPEG); $this->assertEmpty(Storage::disk('icons')->allFiles()); $this->assertTrue($result); } #[Test] public function test_clear_deletes_all_icons_in_database_and_returns_true() { Settings::set('storeIconsInDatabase', true); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_JPEG, base64_decode(OtpTestData::ICON_JPEG_DATA)); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_JPEG, 'content' => OtpTestData::ICON_JPEG_DATA, ]); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, ]); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_JPEG, ]); $result = $this->iconStore->clear(); $this->assertEmpty(Storage::disk('icons')->allFiles()); $this->assertDatabaseEmpty('icons'); $this->assertTrue($result); } #[Test] public function test_clear_empty_disk_returns_true() { $this->assertTrue($this->iconStore->clear()); $this->assertEmpty(Storage::disk('icons')->allFiles()); } #[Test] public function test_clear_empty_disk_deletes_icons_in_database() { Settings::set('storeIconsInDatabase', true); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_JPEG, 'content' => OtpTestData::ICON_JPEG_DATA, ]); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, ]); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_JPEG, ]); $result = $this->iconStore->clear(); $this->assertDatabaseEmpty('icons'); $this->assertTrue($result); } #[Test] public function test_clear_deletes_only_supported_image_format_in_disk() { Storage::disk('icons')->put(OtpTestData::ICON_GIF, base64_decode(OtpTestData::ICON_GIF_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_JPEG, base64_decode(OtpTestData::ICON_JPEG_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_BMP, base64_decode(OtpTestData::ICON_BMP_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_SVG, OtpTestData::ICON_SVG_DATA); Storage::disk('icons')->put(OtpTestData::ICON_WEBP, base64_decode(OtpTestData::ICON_WEBP_DATA)); Storage::disk('icons')->assertExists(OtpTestData::ICON_GIF); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); Storage::disk('icons')->assertExists(OtpTestData::ICON_BMP); Storage::disk('icons')->assertExists(OtpTestData::ICON_SVG); Storage::disk('icons')->assertExists(OtpTestData::ICON_WEBP); $this->iconStore->clear(); Storage::disk('icons')->assertExists(OtpTestData::ICON_GIF); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); Storage::disk('icons')->assertMissing(OtpTestData::ICON_JPEG); Storage::disk('icons')->assertMissing(OtpTestData::ICON_BMP); Storage::disk('icons')->assertMissing(OtpTestData::ICON_SVG); Storage::disk('icons')->assertMissing(OtpTestData::ICON_WEBP); } #[Test] public function test_delete_deletes_provided_icon_and_returns_true() { Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); $this->iconStore->delete(OtpTestData::ICON_PNG); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); } #[Test] public function test_delete_deletes_provided_icon_in_database_and_returns_true() { Settings::set('storeIconsInDatabase', true); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, ]); $this->iconStore->delete(OtpTestData::ICON_PNG); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); $this->assertDatabaseMissing('icons', [ 'name' => OtpTestData::ICON_PNG, ]); } #[Test] public function test_delete_deletes_provided_icon_in_database_when_disk_is_empty() { Settings::set('storeIconsInDatabase', true); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, ]); $this->iconStore->delete(OtpTestData::ICON_PNG); $this->assertDatabaseMissing('icons', [ 'name' => OtpTestData::ICON_PNG, ]); } #[Test] public function test_delete_deletes_provided_icons_and_returns_true() { Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_JPEG, base64_decode(OtpTestData::ICON_JPEG_DATA)); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); $this->iconStore->delete([ OtpTestData::ICON_PNG, OtpTestData::ICON_JPEG, ]); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); Storage::disk('icons')->assertMissing(OtpTestData::ICON_JPEG); } #[Test] public function test_delete_deletes_provided_icons_in_database_and_returns_true() { Settings::set('storeIconsInDatabase', true); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_JPEG, base64_decode(OtpTestData::ICON_JPEG_DATA)); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_JPEG, 'content' => OtpTestData::ICON_JPEG_DATA, ]); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, ]); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_JPEG, ]); $this->iconStore->delete([ OtpTestData::ICON_PNG, OtpTestData::ICON_JPEG, ]); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); Storage::disk('icons')->assertMissing(OtpTestData::ICON_JPEG); $this->assertDatabaseMissing('icons', [ 'name' => OtpTestData::ICON_PNG, ]); $this->assertDatabaseMissing('icons', [ 'name' => OtpTestData::ICON_JPEG, ]); } #[Test] public function test_delete_deletes_provided_icons_in_database_when_disk_is_empty() { Settings::set('storeIconsInDatabase', true); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_JPEG, 'content' => OtpTestData::ICON_JPEG_DATA, ]); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); Storage::disk('icons')->assertMissing(OtpTestData::ICON_JPEG); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, ]); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_JPEG, ]); $this->iconStore->delete([ OtpTestData::ICON_PNG, OtpTestData::ICON_JPEG, ]); $this->assertDatabaseMissing('icons', [ 'name' => OtpTestData::ICON_PNG, ]); $this->assertDatabaseMissing('icons', [ 'name' => OtpTestData::ICON_JPEG, ]); } #[Test] public function test_delete_missing_icon_returns_true() { Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); $result = $this->iconStore->delete(OtpTestData::ICON_PNG); $this->assertTrue($result); } #[Test] public function test_delete_empty_icons_returns_true() { $result = $this->iconStore->delete([]); $this->assertTrue($result); } #[Test] public function test_delete_returns_false_when_it_fails() { Storage::fake('icons'); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::shouldReceive('disk->delete') ->andReturn(false); $result = $this->iconStore->delete(OtpTestData::ICON_PNG); $this->assertFalse($result); } #[Test] public function test_store_writes_the_icon_to_disk_and_returns_true() { Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); $result = $this->iconStore->store(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); $this->assertTrue($result); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); } #[Test] public function test_store_writes_the_icon_to_disk_and_database_and_returns_true() { Settings::set('storeIconsInDatabase', true); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); $this->assertDatabaseMissing('icons', [ 'name' => OtpTestData::ICON_PNG, ]); $result = $this->iconStore->store(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); $this->assertTrue($result); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, ]); } #[Test] public function test_store_returns_false_when_it_fails() { Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); $iconName = OtpTestData::ICON_PNG; $iconContent = ''; Storage::shouldReceive('disk->put') ->with($iconName, $iconContent) ->andReturn(false); Storage::shouldReceive('disk->mimeType') ->with($iconName) ->andReturn('image/png'); $result = $this->iconStore->store($iconName, $iconContent); $this->assertFalse($result); } #[Test] public function test_store_stores_sanitized_svg_content() { Settings::set('storeIconsInDatabase', true); $result = $this->iconStore->store(OtpTestData::ICON_SVG, OtpTestData::ICON_SVG_DATA_INFECTED); $this->assertTrue($result); $this->assertStringNotContainsString( OtpTestData::ICON_SVG_MALICIOUS_CODE, Storage::disk('icons')->get(OtpTestData::ICON_SVG) ); $dbRecord = DB::table('icons')->where('name', OtpTestData::ICON_SVG)->first(); $this->assertStringNotContainsString( OtpTestData::ICON_SVG_MALICIOUS_CODE, $dbRecord->content, ); } #[Test] public function test_store_returns_false_when_svg_sanitize_failed() { $result = $this->iconStore->store(OtpTestData::ICON_SVG, 'this_will_make_svg_data_invalid' . OtpTestData::ICON_SVG_DATA); $this->assertFalse($result); } #[Test] public function test_store_deletes_svg_icon_that_cannot_be_sanitized() { Settings::set('storeIconsInDatabase', true); $result = $this->iconStore->store(OtpTestData::ICON_SVG, 'this_will_make_svg_data_invalid' . OtpTestData::ICON_SVG_DATA); Storage::disk('icons')->assertMissing(OtpTestData::ICON_SVG); $this->assertDatabaseMissing('icons', [ 'name' => OtpTestData::ICON_SVG, ]); } #[Test] public function test_exists_returns_true() { Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); $this->assertTrue($this->iconStore->exists(OtpTestData::ICON_PNG)); } #[Test] public function test_exists_fixes_missing_file_in_disk() { Settings::set('storeIconsInDatabase', true); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); $this->iconStore->exists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); } #[Test] public function test_exists_returns_false() { $this->assertFalse($this->iconStore->exists(OtpTestData::ICON_PNG)); } #[Test] public function test_setDatabaseReplication_stores_icon_files_to_database() { $user = User::factory()->create(); $admin = User::factory()->administrator()->create(); TwoFAccount::factory()->for($user)->create([ 'icon' => OtpTestData::ICON_PNG, ]); TwoFAccount::factory()->for($admin)->create([ 'icon' => OtpTestData::ICON_JPEG, ]); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_JPEG, base64_decode(OtpTestData::ICON_JPEG_DATA)); Settings::set('storeIconsInDatabase', true); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_JPEG, 'content' => OtpTestData::ICON_JPEG_DATA, ]); $this->assertDatabaseCount('icons', 2); } #[Test] public function test_setDatabaseReplication_stores_only_registered_icon_to_database() { $user = User::factory()->create(); TwoFAccount::factory()->for($user)->create([ 'icon' => OtpTestData::ICON_PNG, ]); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_JPEG, base64_decode(OtpTestData::ICON_JPEG_DATA)); Settings::set('storeIconsInDatabase', true); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); $this->assertDatabaseMissing('icons', [ 'name' => OtpTestData::ICON_JPEG, 'content' => OtpTestData::ICON_JPEG_DATA, ]); $this->assertDatabaseCount('icons', 1); } #[Test] public function test_setDatabaseReplication_clears_database_before_replication() { DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); Settings::set('storeIconsInDatabase', true); $this->assertDatabaseEmpty('icons'); } #[Test] public function test_setDatabaseReplication_skips_icon_when_file_is_missing() { $user = User::factory()->create(); TwoFAccount::factory()->for($user)->create([ 'icon' => OtpTestData::ICON_PNG, ]); Storage::disk('icons')->assertMissing(OtpTestData::ICON_PNG); Settings::set('storeIconsInDatabase', true); $this->assertDatabaseEmpty('icons'); } #[Test] public function test_setDatabaseReplication_restores_icons_as_file_and_clears_database() { Settings::set('storeIconsInDatabase', true); $user = User::factory()->create(); $admin = User::factory()->administrator()->create(); TwoFAccount::factory()->for($user)->create([ 'icon' => OtpTestData::ICON_PNG, ]); TwoFAccount::factory()->for($admin)->create([ 'icon' => OtpTestData::ICON_JPEG, ]); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_JPEG, 'content' => OtpTestData::ICON_JPEG_DATA, ]); Settings::set('storeIconsInDatabase', false); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); $this->assertDatabaseEmpty('icons'); } #[Test] public function test_setDatabaseReplication_overrides_existing_files_during_restoration_from_database() { Settings::set('storeIconsInDatabase', true); $user = User::factory()->create(); TwoFAccount::factory()->for($user)->create([ 'icon' => OtpTestData::ICON_PNG, ]); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_JPEG_DATA)); Settings::set('storeIconsInDatabase', false); $this->assertEquals(base64_decode(OtpTestData::ICON_PNG_DATA), Storage::disk('icons')->get(OtpTestData::ICON_PNG)); } #[Test] #[RunInSeparateProcess] #[PreserveGlobalState(false)] public function test_setDatabaseReplication_On_sends_exception_and_does_nothing_if_filling_database_fails() { $user = User::factory()->create(); $admin = User::factory()->administrator()->create(); TwoFAccount::factory()->for($user)->create([ 'icon' => OtpTestData::ICON_PNG, ]); TwoFAccount::factory()->for($admin)->create([ 'icon' => OtpTestData::ICON_JPEG, ]); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_PNG_DATA)); Storage::disk('icons')->put(OtpTestData::ICON_PNG, base64_decode(OtpTestData::ICON_JPEG_DATA)); $this->expectException(FailedIconStoreDatabaseTogglingException::class); $mock = $this->mock('overload:' . Icon::class, function (MockInterface $iconModel) { $iconModel->shouldReceive('truncate') ->andReturn(true); $iconModel->shouldReceive('firstOrNew') ->andThrow(new \Exception); }); Settings::set('storeIconsInDatabase', true); $this->assertDatabaseEmpty('icons'); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); } #[Test] public function test_setDatabaseReplication_Off_sends_exception_and_does_nothing_if_filling_database_fails() { Settings::set('storeIconsInDatabase', true); $user = User::factory()->create(); $admin = User::factory()->administrator()->create(); TwoFAccount::factory()->for($user)->create([ 'icon' => OtpTestData::ICON_PNG, ]); TwoFAccount::factory()->for($admin)->create([ 'icon' => OtpTestData::ICON_JPEG, ]); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); DB::table('icons')->insert([ 'name' => OtpTestData::ICON_JPEG, 'content' => OtpTestData::ICON_JPEG_DATA, ]); Storage::shouldReceive('disk->put') ->once() ->andThrow(new FailedIconStoreDatabaseTogglingException); $this->expectException(FailedIconStoreDatabaseTogglingException::class); Settings::set('storeIconsInDatabase', false); Storage::disk('icons')->assertExists(OtpTestData::ICON_PNG); Storage::disk('icons')->assertExists(OtpTestData::ICON_JPEG); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_PNG, 'content' => OtpTestData::ICON_PNG_DATA, ]); $this->assertDatabaseHas('icons', [ 'name' => OtpTestData::ICON_JPEG, 'content' => OtpTestData::ICON_JPEG_DATA, ]); } }