From 33d7bcb665746e4bf3472a43869fada6fd79f2ae Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 00:50:52 +0900 Subject: [PATCH 01/56] =?UTF-8?q?test:=20=E6=98=94=E3=81=AEMastodon?= =?UTF-8?q?=E4=BA=92=E6=8F=9BAPI=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92=E5=BE=A9=E6=B4=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .../src/test/resources/media/400x400.png | Bin 0 -> 7227 bytes hideout-mastodon/build.gradle.kts | 5 + .../StatusQueryServiceImplTest.kt | 11 + .../account/AccountApiPaginationTest.kt | 160 ++++ .../kotlin/mastodon/account/AccountApiTest.kt | 471 ++++++++++++ .../src/test/kotlin/mastodon/apps/AppTest.kt | 135 ++++ .../test/kotlin/mastodon/filter/FilterTest.kt | 710 ++++++++++++++++++ .../test/kotlin/mastodon/media/MediaTest.kt | 129 ++++ .../ExposedNotificationsApiPaginationTest.kt | 179 +++++ .../MongodbNotificationsApiPaginationTest.kt | 179 +++++ .../test/kotlin/mastodon/status/StatusTest.kt | 232 ++++++ .../mastodon/timelines/TimelineApiTest.kt | 131 ++++ hideout-mastodon/src/test/kotlin/util/Json.kt | 8 + .../kotlin/util/SpringApplicationTestBase.kt | 22 + .../src/test/kotlin/util/TestTransaction.kt | 26 + .../src/test/kotlin/util/WithHttpSignature.kt | 31 + ...WithHttpSignatureSecurityContextFactory.kt | 52 ++ .../test/kotlin/util/WithMockHttpSignature.kt | 35 + ...MockHttpSignatureSecurityContextFactory.kt | 55 ++ .../src/test/resources/application.yml | 4 +- ...iV1AccountsIdFollowPost フォローできる.sql | 17 + .../sql/accounts/test-accounts-statuses.sql | 201 +++++ .../test/resources/sql/filter/test-filter.sql | 4 + ...でフォロワーがfollowers投稿を取得できる.sql | 28 + ...証でフォロワーがpublic投稿を取得できる.sql | 29 + ...でフォロワーがunlisted投稿を取得できる.sql | 29 + ...稿はattachmentにDocumentとして画像が存在する.sql | 25 + ...イになっている投稿はinReplyToが存在する.sql | 20 + ...でfollowers投稿を取得しようとすると404.sql | 17 + .../sql/note/匿名でpublic投稿を取得できる.sql | 17 + .../note/匿名でunlisted投稿を取得できる.sql | 17 + .../test-mastodon_notifications.sql | 66 ++ .../sql/notification/test-notifications.sql | 66 ++ .../src/test/resources/sql/posts.sql | 10 +- .../test/resources/sql/test-custom-emoji.sql | 3 + .../src/test/resources/sql/test-post.sql | 4 + .../src/test/resources/sql/test-user.sql | 11 + .../src/test/resources/sql/test-user2.sql | 10 + .../src/test/resources/sql/userdetail.sql | 2 + 40 files changed, 3146 insertions(+), 6 deletions(-) create mode 100644 hideout-core/src/test/resources/media/400x400.png create mode 100644 hideout-mastodon/src/test/kotlin/mastodon/account/AccountApiPaginationTest.kt create mode 100644 hideout-mastodon/src/test/kotlin/mastodon/account/AccountApiTest.kt create mode 100644 hideout-mastodon/src/test/kotlin/mastodon/apps/AppTest.kt create mode 100644 hideout-mastodon/src/test/kotlin/mastodon/filter/FilterTest.kt create mode 100644 hideout-mastodon/src/test/kotlin/mastodon/media/MediaTest.kt create mode 100644 hideout-mastodon/src/test/kotlin/mastodon/notifications/ExposedNotificationsApiPaginationTest.kt create mode 100644 hideout-mastodon/src/test/kotlin/mastodon/notifications/MongodbNotificationsApiPaginationTest.kt create mode 100644 hideout-mastodon/src/test/kotlin/mastodon/status/StatusTest.kt create mode 100644 hideout-mastodon/src/test/kotlin/mastodon/timelines/TimelineApiTest.kt create mode 100644 hideout-mastodon/src/test/kotlin/util/Json.kt create mode 100644 hideout-mastodon/src/test/kotlin/util/SpringApplicationTestBase.kt create mode 100644 hideout-mastodon/src/test/kotlin/util/TestTransaction.kt create mode 100644 hideout-mastodon/src/test/kotlin/util/WithHttpSignature.kt create mode 100644 hideout-mastodon/src/test/kotlin/util/WithHttpSignatureSecurityContextFactory.kt create mode 100644 hideout-mastodon/src/test/kotlin/util/WithMockHttpSignature.kt create mode 100644 hideout-mastodon/src/test/kotlin/util/WithMockHttpSignatureSecurityContextFactory.kt create mode 100644 hideout-mastodon/src/test/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql create mode 100644 hideout-mastodon/src/test/resources/sql/accounts/test-accounts-statuses.sql create mode 100644 hideout-mastodon/src/test/resources/sql/filter/test-filter.sql create mode 100644 hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql create mode 100644 hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql create mode 100644 hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql create mode 100644 hideout-mastodon/src/test/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql create mode 100644 hideout-mastodon/src/test/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql create mode 100644 hideout-mastodon/src/test/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql create mode 100644 hideout-mastodon/src/test/resources/sql/note/匿名でpublic投稿を取得できる.sql create mode 100644 hideout-mastodon/src/test/resources/sql/note/匿名でunlisted投稿を取得できる.sql create mode 100644 hideout-mastodon/src/test/resources/sql/notification/test-mastodon_notifications.sql create mode 100644 hideout-mastodon/src/test/resources/sql/notification/test-notifications.sql create mode 100644 hideout-mastodon/src/test/resources/sql/test-custom-emoji.sql create mode 100644 hideout-mastodon/src/test/resources/sql/test-post.sql create mode 100644 hideout-mastodon/src/test/resources/sql/test-user.sql create mode 100644 hideout-mastodon/src/test/resources/sql/test-user2.sql create mode 100644 hideout-mastodon/src/test/resources/sql/userdetail.sql diff --git a/.gitignore b/.gitignore index e3b32bdc..ecde199b 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,4 @@ out/ /hideout-mastodon/.kotlin/sessions/ /http-client.private.env.json /logs/ +/hideout-mastodon/logs/ diff --git a/hideout-core/src/test/resources/media/400x400.png b/hideout-core/src/test/resources/media/400x400.png new file mode 100644 index 0000000000000000000000000000000000000000..0d2e71bee323fed58e3aab0a839c0c2044bba54f GIT binary patch literal 7227 zcmeHM`8$+d+~?`hLQ0!tt0W>JyTKrmEh5>MWFK3ykFD}ZVo;XSFp@3%mLX$I@z|4P zVvLDVV~H`Q84U)*d%E7=-+$nJez>o>uDQ>B&i8!JclmriC*_vK4Srr>UM?;!eiLIu zYc4MC%sme`qUtG7& z>v3_({(X>3FX_KQ|GD7*Uld5h^6XkzSd`dSai~6Lp|P3va%v630cuF=3Y(H~m`MvM zC#dD}_xtv5N8kN>@2ZL9@y7Oc?NJZKr3lQQA)~&=V2DNe1=J!(yEaN&KF{1}Y)K_) z4Y|dfPgM~{Byd)A_t+U4>Bf#=*wKX#ga;2)OsKgxjhbJhXpL3e?oqEgbL}r-p0l z=rr$79sb1BC^r&9gF!i~+%7ZqIF-@I9H zZX#w64h~kt+BQ4pG&Ly$e;e$nqZUoDt}o$OdGPAb*iqjwiNN@;0)Z_g>q{p~Y-Ib_ z*U@tF@=#=3QH-z5M4cPX6h|)H^f|@Lqp7Ves;RwOVO!PjmcY5lg6q^%U@F2)f?EPY zRDAF2QrO()W)w{SuoxkHo{rl?_2sbYzI^%e=iicFn|DgBpIa6}O`3>@S6YLDgXi(( zmL4vTn!#4JwX=b@eQs<0{q)oP{Cr}_tVwHI8*lX_a43aB(M!h=0|rJ%t?qI=$_bWF zV7h;TX?vDG9;N~hbR_JF_r(BfG$D{JLVc|**dT@C5#pkr>2diaFOx=U@v+i6?0)8% zpK!ts5-B2clD7kwWiEB`xv{af_-R6T>2#18_{g=+XNMDyQ@C;C29rU#!Mbl-j*nK+ z-mk7kVYL3!<-QaKd61AmCtVQzCgR}YQrfp*TxxxFW|41-#cDp8+FeA&lIeTZkxp0E zfiYlD8E17XgX>!yYi@L15KQG%Z```{dkt0S7UkmXY^)+&u*vCnxS$s=(+9k4F(0}E zpG!?mZER?8&mWp=tIZzt0+#l;KLjQ%E-p4=FjWxr;Gmhm-gSv%(X8bh&n5@TP^VGx z`Ij$WP87Wduc8@0uFrZ9M*dg|heL9P8B{qhr8E7DYcEVo(^&B!%Rh@jztp69cwCAlU0QIK`{0ZelS|w6ZTvm ze8>+kGm*`C!QsU9dpGqEwmG}Sb}p|_e$$JX*4FwNHwP!DEG$;XBkJ&STwvhM^^J`h zu?%olA8@#{?AFTh%5ZOYiRYOcbh49{nS_LynOP$arvQSuhk%)`b#`;pT@sei+a-em zYWVVbkNw3CyQ0oD?%3+$%8|79f&i$eK`@jNvu2A^Y!YO}k( z*SE)QPe9g|K^3|E0jF~L@25K&6_);GnKd_lXr#BtbKoT#&%pTQ@yitdA#eN?M(G0< z+wA%b2WP?N+{-~SizrMV7{=UHwJN?C*);O3R%9wp0 zoWH=?x&tSjNpz_!lW_#ySn^)r$~a85{)~dqO&nQ$W)b;s<$g{)8IrvPj2y>4VzI)h zIrjxv9j&dtSor#hj9#z6z@aS%{3{6^zG0}Iyu5rGr5r8ZtpTza;qj&DRv(;vR|u@M zxdv;7gnhTI8h<_$BSZ|C*c5B4)oPYTF@np>%X_48|GbTl#Q?drz1 z0l&xe%#3jGa`LsJhO+ZU633{wf1*F~zNWT~!J5-Qb|0pfuH1kW<)a z1%_DCa=1PE_0Hl8NIb0hH6xgASJ(Bl`(ESw_bPaJA=*a^K~PJ&`rJ58TTM&O>6l-P z$G&t*-`Lm-2Iq3lK(V{8R&8l%X+!xrc?AU#p9p?oMhW2vQ`<5MUQ5+SQDr zCnoOmu&=JIO^>zof8kh@%YeE;3UXtiXEy~>scjSAt3s$cf~h8u0=4z!|DCpK!(2)^ zLg&w{T7fyHUOx}*!)5tI^ZbZL<>%*X{|ryQc0PJ-VaU(|2Kp4lOX=yje;~s9)e-_t z&YKHiZF4GqkBRj*Jo$HMXvp{kfBc4CVC@Q`8o$R;DXxw+L8JUGuvku8K#mqu~W$f3OQJ5LorSlljeX=#y0UwlXlMw(0Qi?07t zH^VvnL`C`zosW-iB7v-Z#6O)%VlSiI+L)J^e;aT^*r6u@q*6>ZG;R0$&KZ#ju(4hO5%P{JB5&?x-QfVlMgRvV!;o zaB#t6ROK_^ygEBOCwouvCM~?3DW7-X>ATBIsncN^OG;>IX`SE%I1OKVCq8?(tHO$p zuuVre3q!~hdc=ZVt9}FarCVa-sqjqd9pa4t zl;zJOYLZHzmy5w1GQ6AoMBA8r?;IGIVfCf+YRhr!EGYl5l-|I6V~Ed2ivP)(_ zmvNK4Gb!X|anbNw{rR?J<)q?EhmT=hM2bZN9`Z{CyulAOZSBxrFn zMPxx+lS#|UZ}gWHC8a3!?GKDmz;!lb1w9j)+v;B`t-xL>0cY^Hau=f~;*`-XEsL;( zEP$dYcg7^kS9S;JfA8i~3%J-rlM$!$*E18{5_ubMlr6E%i}l%9LbWi6{>Jsb)b1ZR z)B}027_yES5K&#K@EAa^xrK#=Ps5=fz8RLUSkt?}@Y+`CrT+bWcO&)jvY0GXqn4@u zaN7-U{}p}lmu{5&o+n0XDTbYGqPzY5DXq1aK@p!kl-FZ3X*HRS-V^<$c)-bn`{I%0I~~W%20etq+HA zikAdady1-9ESBEHOe@a}OEL@N!{`>w#7Bt3EUT>97N8A?5>Msdzy=Ti0 zb4;QV_7xa;YycM{O@H3{3d4`)g%^9{bgdP_qzcYJ*Oqur<9Bspop)HA7HLqt8? z*;ksOvZNR`>tLYr*kf&Zk`V-t5>qknQV+joxVxeFeP(9n+eD1y@#g_*Rh5yrs(-h) zW2oc-8#f zD7$lCxA9E5NXdL2C&u5zHz24IL_ zzqZ=?H0y=7+Dd)m#6BtuKCvN^6L^Li?RRTBDDtPvp%^SGzo5WsM7eeY6j)ISzNBj% zI&q|sW)khA_r0MQ?12=nypTjCmj!=N6Fv6b7wwHSN+(-9DZ742HGr;M(=B(_V=BsI zu6JKznMmO{Ec{*7spYr_tRVP(>$zT?GdScpy5NA$FyD&nQad3g^I)b-1I=NE%KD4w z+cTkh#Q!2>bfPj^~*D{N$scBH!2spB0S*s;)&r6ts& zgLMAN>Z+rU0MTNS5#=l>D41qoi!kz7xtP>b6NyjI?T1^I<3D%4_F+V6|8h8jX0I%T zIkFt`%zNzb&OdOlwYB})OQdfgu)fF6$l3%VYF+Eh>IfqK3=@14Zb4 zXM3lDKoT&Q@Z|>#{%Ok3X|Asq@XeSA-bn}vu?lAndMfpB0r2d>1BkIIYQ>;vWP}@V zGx42v+o}|5n}<%_)jAeb=CJ$C=QX3>W@ge=MFEjclkRl4RBEvQJel=d+tRf3#a1gE zi((9Tk398RT3#NAI_~J~99wVqxwG?e_<^pqwKcu+htOnrosFyqzekSgMUUBwS^Y(* zk1ZTm9JyuxM@2xf!_DR#2-_tB=Wb`4OCh?{D5!Tgkq1-KCa4XZS{gRlO8zC{lVEDM zWRB_33VkF%4MD;`>2jy8zh}qJ2sLuz3mqH;K~w3evLl3#OT%zzr2$j!tap*51f;Pf zYEJo_#NT~iiSS0iN-9wSASKpI4p@Fa>K`6HuHi|5H3OcU9_x&C9d0$P?#tM|({zud z>^#@YTtq*C+OJQ0DrP4olk;f7anaEguccf;Jayemr=*2h`o_gg+tVW>BP-8D0L0YF zn4E1w$^PXz&`7LiFp1$Vnp#>Se)4eOVtE(c&3vmM>l?*Z{?~xdS7Ea}N->qnn#kfdaPao`_wU)3239#@)WGCX^iFzc0H8XoXV=&2e=aRm zgbPKx+Q}dMi(84Npe>4aP5KH`)zs8HBWnnHv#6-3kmXp>En_Bor?1yLX7v-WMngjg z*4D5X{ouiadtz^+0L1y6dj^Nas@8_jx9D!w1=z^|h~8Sd61u37uKLQXbZq44eKq7w z@S!5AM6B0}#av^zGlGHUF#qe<{dWQ(E_Ue|88sVF722;BNTJmaJgAY?p`(NIjiO>= z4(0nm+3LP$1x?ru&?yQI2zZyfmfn4D;xRo8!ep=cuy;8a)!AiMo2an^YBm9D?*MZ%stn(d!u@VS`4(Z=RLpR6e z8j_ND{9BtHudsL6P4p4Z8e35E_5m58hX8Va5yrD<5;c}8^QG#(h8zZiVUqWD2~j*& zb%goZS-ltibHgI{Iq_})M}x9NZlL7koT8rkqUhQYD+5|_6wg)r9?I61BPap?QbGqH{+Z4z!ZEdjj*B^k!10Xk^qp^UXXfy)Q zTBw_#_NAk89A;fL4&s>;3-$f=kOov2dRh%=A`Os>03QSXADq9R43v(!IYS^6OXism zfP{)dNf%fwj>0p5)P%uo&!Ou%r?{0aG}xO*L`H)17?~;#RzqI6BK^W#s;23wQA1PH zg&Nzzsmm*2kPC>7qY+Hxcw*xG1ESE=c)Jr_`BAXusYJTFVz#QnV8?JO@E-vG2+^}= zov7GR-?ZO~EBzpx1(@mfno3mt7zhMi&IyfAT zUfJdq1%<)g-S~4lJHW^E87$x2_i~`MZEtVCuqgLoibX=is2VZQLOb2G(?^o$SyVy~ z;Z=@TZoj8zaBy(-f!hZFgo~4;l*IC5Q*DM#|czK zXzb=2@ylY`m|yEOl3t89K;x^cwSWdYikV)%e3|*ZD>)Ck76OOEM44+yE7fXqDUSm8 zu4=ia($b6UO-AvSCk@c%xNTd2`u2$(L4ehI&nEOOER;dA0qU6VNMC+a{)ybQ(yvMBBn4;4o21|$#9S5gWOW@^qwqd?pN9pWVr zDQl@fqC4IjA}OA+*IuN~x3RGSLP7xul3Sb(5Cz}wZ!SK#1gb?pS;Md%s8>Lpsj)R{ zo38y0*Ey8j1tbAEIXPpcynJHTw;}H}Hs&__U1x literal 0 HcmV?d00001 diff --git a/hideout-mastodon/build.gradle.kts b/hideout-mastodon/build.gradle.kts index 2265937b..12ad6ee8 100644 --- a/hideout-mastodon/build.gradle.kts +++ b/hideout-mastodon/build.gradle.kts @@ -60,9 +60,14 @@ dependencies { implementation(libs.bundles.coroutines) testImplementation("org.springframework.boot:spring-boot-starter-test") + testImplementation("org.springframework.security:spring-security-test") + testImplementation(libs.bundles.spring.boot.oauth2) testImplementation(libs.kotlin.junit) testImplementation(libs.coroutines.test) testImplementation(libs.h2db) + testImplementation(libs.flyway.core) + testImplementation(libs.http.signature) + testRuntimeOnly(libs.flyway.postgresql) } diff --git a/hideout-mastodon/src/test/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImplTest.kt b/hideout-mastodon/src/test/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImplTest.kt index da7ef30c..abf5bea5 100644 --- a/hideout-mastodon/src/test/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImplTest.kt +++ b/hideout-mastodon/src/test/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/StatusQueryServiceImplTest.kt @@ -6,6 +6,8 @@ import dev.usbharu.hideout.core.domain.model.support.acct.Acct import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId import kotlinx.coroutines.test.runTest +import org.flywaydb.core.Flyway +import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.Assertions.assertNull import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired @@ -30,4 +32,13 @@ class StatusQueryServiceImplTest { assertNull(status) } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } } \ No newline at end of file diff --git a/hideout-mastodon/src/test/kotlin/mastodon/account/AccountApiPaginationTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/account/AccountApiPaginationTest.kt new file mode 100644 index 00000000..b2057786 --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/mastodon/account/AccountApiPaginationTest.kt @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mastodon.account + +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import dev.usbharu.hideout.SpringApplication +import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.Status +import org.assertj.core.api.Assertions.assertThat +import org.flywaydb.core.Flyway +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers +import org.springframework.test.context.jdbc.Sql +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.get +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.context.WebApplicationContext + +@SpringBootTest(classes = [SpringApplication::class]) +@AutoConfigureMockMvc +@Transactional +@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +@Sql("/sql/accounts/test-accounts-statuses.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +class AccountApiPaginationTest { + @Autowired + private lateinit var context: WebApplicationContext + + private lateinit var mockMvc: MockMvc + + @Test + fun `apiV1AccountsIdStatusesGet 投稿を取得できる`() { + val content = mockMvc + .get("/api/v1/accounts/1/statuses"){ + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + .andExpect { header { string("Link","; rel=\"next\", ; rel=\"prev\"") } } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + assertThat(value.first().id).isEqualTo("100") + assertThat(value.last().id).isEqualTo("81") + assertThat(value).size().isEqualTo(20) + } + + @Test + fun `apiV1AccountsIdStatusesGet 結果が0件のときはLinkヘッダーがない`() { + val content = mockMvc + .get("/api/v1/accounts/1/statuses?min_id=100"){ + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .andDo { print() } + .asyncDispatch() + .andExpect { status { isOk() } } + .andExpect { header { doesNotExist("Link") } } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + + assertThat(value).isEmpty() + } + + @Test + fun `apiV1AccountsIdStatusesGet maxIdを指定して取得`() { + val content = mockMvc + .get("/api/v1/accounts/1/statuses?max_id=100"){ + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + .andExpect { header { string("Link","; rel=\"next\", ; rel=\"prev\"") } } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + assertThat(value.first().id).isEqualTo("99") + assertThat(value.last().id).isEqualTo("80") + assertThat(value).size().isEqualTo(20) + } + + @Test + fun `apiV1AccountsIdStatusesGet minIdを指定して取得`() { + val content = mockMvc + .get("/api/v1/accounts/1/statuses?min_id=1"){ + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + .andExpect { header { string("Link","; rel=\"next\", ; rel=\"prev\"") } } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + assertThat(value.first().id).isEqualTo("21") + assertThat(value.last().id).isEqualTo("2") + assertThat(value).size().isEqualTo(20) + } + + @BeforeEach + fun setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()) + .build() + } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } +} \ No newline at end of file diff --git a/hideout-mastodon/src/test/kotlin/mastodon/account/AccountApiTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/account/AccountApiTest.kt new file mode 100644 index 00000000..c1e5c1be --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/mastodon/account/AccountApiTest.kt @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mastodon.account + +import dev.usbharu.hideout.SpringApplication +import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository +import dev.usbharu.hideout.core.infrastructure.exposedrepository.ExposedRelationshipRepository +import kotlinx.coroutines.test.runTest +import org.assertj.core.api.Assertions.assertThat +import org.flywaydb.core.Flyway +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.http.MediaType +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.test.context.support.WithAnonymousUser +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity +import org.springframework.test.context.jdbc.Sql +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.get +import org.springframework.test.web.servlet.post +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.context.WebApplicationContext + +@SpringBootTest(classes = [SpringApplication::class]) +@AutoConfigureMockMvc +@Transactional +@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +class AccountApiTest { + + @Autowired + private lateinit var actorRepository: ActorRepository + + @Autowired + lateinit var relationshipRepository: ExposedRelationshipRepository + + @Autowired + private lateinit var context: WebApplicationContext + + private lateinit var mockMvc: MockMvc + + @BeforeEach + fun setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(springSecurity()) + .build() + } + + @Test + fun `apiV1AccountsVerifyCredentialsGetにreadでアクセスできる`() { + mockMvc + .get("/api/v1/accounts/verify_credentials") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))) + } + .asyncDispatch() + .andDo { print() } + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsVerifyCredentialsGetにread_accountsでアクセスできる`() { + mockMvc + .get("/api/v1/accounts/verify_credentials") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:accounts"))) + } + .asyncDispatch() + .andDo { print() } + .andExpect { status { isOk() } } + } + + @Test + @WithAnonymousUser + fun apiV1AccountsVerifyCredentialsGetに匿名でアクセスすると401() { + mockMvc + .get("/api/v1/accounts/verify_credentials") + .andExpect { status { isUnauthorized() } } + } + + @Test + @WithAnonymousUser + fun apiV1AccountsPostに匿名でPOSTしたらアカウントを作成できる() = runTest { + mockMvc + .post("/api/v1/accounts") { + contentType = MediaType.APPLICATION_FORM_URLENCODED + param("username", "api-test-user-1") + param("password", "very-secure-password") + param("email", "test@example.com") + param("agreement", "true") + param("locale", "") + with(csrf()) + } + .asyncDispatch() + .andExpect { status { isFound() } } + + actorRepository.findByNameAndDomain("api-test-user-1", "example.com") + } + + @Test + @WithAnonymousUser + fun apiV1AccountsPostで必須パラメーター以外を省略しても作成できる() = runTest { + mockMvc + .post("/api/v1/accounts") { + contentType = MediaType.APPLICATION_FORM_URLENCODED + param("username", "api-test-user-2") + param("password", "very-secure-password") + with(csrf()) + } + .asyncDispatch() + .andExpect { status { isFound() } } + + actorRepository.findByNameAndDomain("api-test-user-2", "example.com") + } + + @Test + @WithAnonymousUser + fun apiV1AccountsPostでusernameパラメーターを省略したら400() = runTest { + mockMvc + .post("/api/v1/accounts") { + contentType = MediaType.APPLICATION_FORM_URLENCODED + param("password", "api-test-user-3") + with(csrf()) + } + .andDo { print() } + .andExpect { status { isUnprocessableEntity() } } + } + + @Test + @WithAnonymousUser + fun apiV1AccountsPostでpasswordパラメーターを省略したら400() = runTest { + mockMvc + .post("/api/v1/accounts") { + contentType = MediaType.APPLICATION_FORM_URLENCODED + param("username", "api-test-user-4") + with(csrf()) + } + .andExpect { status { isUnprocessableEntity() } } + } + + @Test + @Disabled("JSONでも作れるようにするため") + @WithAnonymousUser + fun apiV1AccountsPostでJSONで作ろうとしても400() { + mockMvc + .post("/api/v1/accounts") { + contentType = MediaType.APPLICATION_JSON + content = """{"username":"api-test-user-5","password":"very-very-secure-password"}""" + with(csrf()) + } + .andExpect { status { isUnsupportedMediaType() } } + } + + @Test + @WithAnonymousUser + fun apiV1AccountsPostにCSRFトークンは必要() { + mockMvc + .post("/api/v1/accounts") { + contentType = MediaType.APPLICATION_FORM_URLENCODED + param("username", "api-test-user-2") + param("password", "very-secure-password") + } + .andExpect { status { isForbidden() } } + } + + @Test + @WithAnonymousUser + fun `apiV1AccountsIdGet 匿名でアカウント情報を取得できる`() { + mockMvc + .get("/api/v1/accounts/1") + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsIdFollowPost write_follows権限でPOSTでフォローできる`() { + mockMvc + .post("/api/v1/accounts/2/follow") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:follows"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsIdFollowPost write権限でPOSTでフォローできる`() { + mockMvc + .post("/api/v1/accounts/2/follow") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsIdFollowPost read権限でだと403`() { + mockMvc + .post("/api/v1/accounts/2/follow") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))) + } + .andExpect { status { isForbidden() } } + } + + @Test + @WithAnonymousUser + fun `apiV1AAccountsIdFollowPost 匿名だと401`() { + mockMvc + .post("/api/v1/accounts/2/follow") { + contentType = MediaType.APPLICATION_JSON + with(csrf()) + } + .andExpect { status { isUnauthorized() } } + } + + @Test + @WithAnonymousUser + fun `apiV1AAccountsIdFollowPost 匿名の場合通常csrfトークンは持ってないので403`() { + mockMvc + .post("/api/v1/accounts/2/follow") { + contentType = MediaType.APPLICATION_JSON + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV1AccountsRelationshipsGet 匿名だと401`() { + mockMvc + .get("/api/v1/accounts/relationships") + .andExpect { status { isUnauthorized() } } + } + + @Test + fun `apiV1AccountsRelationshipsGet read_follows権限を持っていたら取得できる`() { + mockMvc + .get("/api/v1/accounts/relationships") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:follows"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsRelationshipsGet read権限を持っていたら取得できる`() { + mockMvc + .get("/api/v1/accounts/relationships") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsRelationshipsGet write権限だと403`() { + mockMvc + .get("/api/v1/accounts/relationships") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .andExpect { status { isForbidden() } } + } + + @Test + @Sql("/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql") + fun `apiV1AccountsIdFollowPost フォローできる`() = runTest { + mockMvc + .post("/api/v1/accounts/3733363/follow") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "37335363") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + + + val alreadyFollow = relationshipRepository.findByActorIdAndTargetId(ActorId(3733363),ActorId(37335363))?.following + + + assertThat(alreadyFollow).isTrue() + } + + @Test + fun `apiV1AccountsIdMutePost write権限でミュートできる`() { + mockMvc + .post("/api/v1/accounts/2/mute") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsIdMutePost write_mutes権限でミュートできる`() { + mockMvc + .post("/api/v1/accounts/2/mute") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:mutes"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsIdMutePost read権限だと403`() = runTest { + mockMvc + .post("/api/v1/accounts/2/mute") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))) + } + .andExpect { status { isForbidden() } } + } + + @Test + @WithAnonymousUser + fun `apiV1AccountsIdMutePost 匿名だと401`() = runTest { + mockMvc + .post("/api/v1/accounts/2/mute") { + contentType = MediaType.APPLICATION_JSON + with(csrf()) + } + .andExpect { status { isUnauthorized() } } + } + + @Test + @WithAnonymousUser + fun `apiV1AccountsIdMutePost csrfトークンがないと403`() = runTest { + mockMvc + .post("/api/v1/accounts/2/mute") { + contentType = MediaType.APPLICATION_JSON + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV1AccountsIdUnmutePost write権限でアンミュートできる`() { + mockMvc + .post("/api/v1/accounts/2/unmute") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsIdUnmutePost write_mutes権限でアンミュートできる`() { + mockMvc + .post("/api/v1/accounts/2/unmute") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:mutes"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1AccountsIdUnmutePost read権限だと403`() = runTest { + mockMvc + .post("/api/v1/accounts/2/unmute") { + contentType = MediaType.APPLICATION_JSON + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))) + } + .andExpect { status { isForbidden() } } + } + + @Test + @WithAnonymousUser + fun `apiV1AccountsIdUnmutePost 匿名だと401`() = runTest { + mockMvc + .post("/api/v1/accounts/2/unmute") { + contentType = MediaType.APPLICATION_JSON + with(csrf()) + } + .andExpect { status { isUnauthorized() } } + } + + @Test + @WithAnonymousUser + fun `apiV1AccountsIdUnmutePost csrfトークンがないと403`() = runTest { + mockMvc + .post("/api/v1/accounts/2/unmute") { + contentType = MediaType.APPLICATION_JSON + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV1MutesGet read権限でミュートしているアカウント一覧を取得できる`() { + mockMvc + .get("/api/v1/mutes") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1MutesGet read_mutes権限でミュートしているアカウント一覧を取得できる`() { + mockMvc + .get("/api/v1/mutes") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:mutes"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1MutesGet write権限だと403`() { + mockMvc + .get("/api/v1/mutes") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .andExpect { status { isForbidden() } } + } + + @Test + @WithAnonymousUser + fun `apiV1MutesGet 匿名だと401`() { + mockMvc + .get("/api/v1/mutes") + .andExpect { status { isUnauthorized() } } + } + + @Test + fun `apiV1AccountsIdStatusesGet read権限で取得できる`() { + mockMvc + .get("/api/v1/accounts/1/statuses") + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + @WithAnonymousUser + fun `apiV1AccountsIdStatusesGet 匿名でもpublic投稿を取得できる`() { + mockMvc + .get("/api/v1/accounts/1/statuses") + .asyncDispatch() + .andExpect { status { isOk() } } + } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } +} diff --git a/hideout-mastodon/src/test/kotlin/mastodon/apps/AppTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/apps/AppTest.kt new file mode 100644 index 00000000..1b80163c --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/mastodon/apps/AppTest.kt @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mastodon.apps + +import dev.usbharu.hideout.SpringApplication +import org.assertj.core.api.Assertions.assertThat +import org.flywaydb.core.Flyway +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.http.MediaType +import org.springframework.jdbc.core.JdbcOperations +import org.springframework.security.oauth2.server.authorization.client.JdbcRegisteredClientRepository +import org.springframework.security.test.context.support.WithAnonymousUser +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.post +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.context.WebApplicationContext +import util.objectMapper +import kotlin.test.assertNotNull + +@SpringBootTest(classes = [SpringApplication::class]) +@AutoConfigureMockMvc +@Transactional +class AppTest { + + @Autowired + private lateinit var context: WebApplicationContext + + private lateinit var mockMvc: MockMvc + + @Autowired + lateinit var jdbcOperations: JdbcOperations + + + val registeredClientRepository: JdbcRegisteredClientRepository by lazy { + JdbcRegisteredClientRepository( + jdbcOperations + ) + } + + @BeforeEach + fun setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()) + .build() + } + + @Test + @WithAnonymousUser + fun apiV1AppsPostにformで匿名でappを作成できる() { + val contentAsString = mockMvc + .post("/api/v1/apps") { + contentType = MediaType.APPLICATION_FORM_URLENCODED + param("client_name", "test-client") + param("redirect_uris", "https://example.com") + param("scopes", "write read") + param("website", "https://example.com") + } + .asyncDispatch() + .andExpect { status { isOk() } } + .andReturn() + .response + .contentAsString + + val clientId = objectMapper().readTree(contentAsString)["client_id"].asText() + + + val registeredClient = registeredClientRepository.findByClientId(clientId) + + assertNotNull(registeredClient) + assertThat(registeredClient.clientName).isEqualTo("test-client") + assertThat(registeredClient.redirectUris.joinToString(",")).isEqualTo("https://example.com") + assertThat(registeredClient.scopes.joinToString(",")).isEqualTo("read,write") + } + + @Test + @WithAnonymousUser + fun apiV1AppsPostにjsonで匿名でappを作成できる() { + val contentAsString = mockMvc + .post("/api/v1/apps") { + contentType = MediaType.APPLICATION_JSON + content = """{ + "client_name": "test-client-2", + "redirect_uris": "https://example.com", + "scopes": "write read", + "website": "https;//example.com" +}""" + } + .asyncDispatch() + .andExpect { status { isOk() } } + .andReturn() + .response + .contentAsString + + val clientId = objectMapper().readTree(contentAsString)["client_id"].asText() + + + val registeredClient = registeredClientRepository.findByClientId(clientId) + + assertNotNull(registeredClient) + assertThat(registeredClient.clientName).isEqualTo("test-client-2") + assertThat(registeredClient.redirectUris.joinToString(",")).isEqualTo("https://example.com") + assertThat(registeredClient.scopes.joinToString(",")).isEqualTo("read,write") + } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } +} diff --git a/hideout-mastodon/src/test/kotlin/mastodon/filter/FilterTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/filter/FilterTest.kt new file mode 100644 index 00000000..73615a07 --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/mastodon/filter/FilterTest.kt @@ -0,0 +1,710 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mastodon.filter + +import dev.usbharu.hideout.SpringApplication +import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.FilterKeywordsPostRequest +import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.FilterPostRequest +import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.FilterPostRequestKeyword +import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.V1FilterPostRequest +import kotlinx.coroutines.test.runTest +import org.flywaydb.core.Flyway +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.http.MediaType +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers +import org.springframework.test.context.jdbc.Sql +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.delete +import org.springframework.test.web.servlet.get +import org.springframework.test.web.servlet.post +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.context.WebApplicationContext +import util.objectMapper + +@SpringBootTest(classes = [SpringApplication::class]) +@AutoConfigureMockMvc +@Transactional +@Sql("/sql/actors.sql", "/sql/userdetail.sql","/sql/filter/test-filter.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +class FilterTest { + @Autowired + private lateinit var context: WebApplicationContext + + private lateinit var mockMvc: MockMvc + + @BeforeEach + fun setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()) + .build() + } + + @Test + fun `apiV2FiltersPost write権限で追加できる`() { + mockMvc + .post("/api/v2/filters") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper().writeValueAsString( + FilterPostRequest( + title = "mute test", + context = listOf(FilterPostRequest.Context.home, FilterPostRequest.Context.public), + filterAction = FilterPostRequest.FilterAction.warn, + expiresIn = null, + keywordsAttributes = listOf( + FilterPostRequestKeyword( + keyword = "hoge", + wholeWord = false, + regex = true + ) + ) + ) + ) + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + .andExpect { + content { + jsonPath("$.keywords[0].keyword") { + value("hoge") + } + } + } + } + + @Test + fun `apiV2FiltersPost write_filters権限で追加できる`() { + mockMvc + .post("/api/v2/filters") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper().writeValueAsString( + FilterPostRequest( + title = "mute test", + context = listOf(FilterPostRequest.Context.home, FilterPostRequest.Context.public), + filterAction = FilterPostRequest.FilterAction.warn, + expiresIn = null, + keywordsAttributes = listOf( + FilterPostRequestKeyword( + keyword = "fuga", + wholeWord = true, + regex = false + ) + ) + ) + ) + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + .andExpect { + content { + jsonPath("$.keywords[0].keyword") { + value("fuga") + } + } + } + } + + @Test + fun `apiV2FiltersPost read権限で401`() { + mockMvc + .post("/api/v2/filters") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper().writeValueAsString( + FilterPostRequest( + title = "mute test", + context = listOf(FilterPostRequest.Context.home, FilterPostRequest.Context.public), + filterAction = FilterPostRequest.FilterAction.warn, + expiresIn = null, + keywordsAttributes = listOf( + FilterPostRequestKeyword( + keyword = "fuga", + wholeWord = true, + regex = false + ) + ) + ) + ) + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV2FiltersGet read権限で取得できる`() { + mockMvc + .get("/api/v2/filters") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersGet read_filters権限で取得できる`() { + mockMvc + .get("/api/v2/filters") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersGet write権限で401`() { + mockMvc + .get("/api/v2/filters") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV2FiltersIdGet read権限で取得できる`() { + mockMvc + .get("/api/v2/filters/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + + @Test + fun `apiV2FiltersIdGet read_filters権限で取得できる`() { + mockMvc + .get("/api/v2/filters/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersIdGet write権限で401`() { + mockMvc + .get("/api/v2/filters/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV2FiltersFilterIdKeywordsGet read権限で取得できる`() { + mockMvc + .get("/api/v2/filters/1/keywords") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersFilterIdKeywordsGet read_filters権限で取得できる`() { + mockMvc + .get("/api/v2/filters/1/keywords") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersFilterIdKeywordsGet writeで403`() { + mockMvc + .get("/api/v2/filters/1/keywords") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV2FiltersFilterIdKeywordsPost writeで追加できる`() { + mockMvc + .post("/api/v2/filters/1/keywords") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper().writeValueAsString( + FilterKeywordsPostRequest( + "hage", false, false + ) + ) + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersFilterIdKeywordsPost write_filtersで追加できる`() { + mockMvc + .post("/api/v2/filters/1/keywords") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper().writeValueAsString( + FilterKeywordsPostRequest( + "hage", false, false + ) + ) + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersFilterIdKeywordsPost readで403`() { + mockMvc + .post("/api/v2/filters/1/keywords") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper().writeValueAsString( + FilterKeywordsPostRequest( + "hage", false, false + ) + ) + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV2FiltersKeywordsIdGet readで取得できる`() { + mockMvc + .get("/api/v2/filters/keywords/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersKeywordsIdGet read_filtersで取得できる`() { + mockMvc + .get("/api/v2/filters/keywords/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersKeywordsIdGet writeだと403`() { + mockMvc + .get("/api/v2/filters/keywords/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV2FiltersKeyowrdsIdDelete writeで削除できる`() = runTest { + mockMvc + .delete("/api/v2/filters/keywords/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersKeyowrdsIdDelete write_filtersで削除できる`() = runTest { + mockMvc + .delete("/api/v2/filters/keywords/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersKeyowrdsIdDelete readで403`() = runTest { + mockMvc + .delete("/api/v2/filters/keywords/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV2FiltersFilterIdStatuses readで取得できる`() { + mockMvc + .get("/api/v2/filters/1/statuses") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersFilterIdStatuses read_filtersで取得できる`() { + mockMvc + .get("/api/v2/filters/1/statuses") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersFilterIdStatuses writeで403`() { + mockMvc + .get("/api/v2/filters/1/statuses") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV2FiltersStatusesIdGet readで取得できる`() { + mockMvc + .get("/api/v2/filters/statuses/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersStatusesIdGet read_filtersで取得できる`() { + mockMvc + .get("/api/v2/filters/statuses/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersStatusesIdGet writeで403`() { + mockMvc + .get("/api/v2/filters/statuses/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV2FiltersStatusesIdDelete writeで削除できる`() { + mockMvc + .delete("/api/v2/filters/statuses/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersStatusesIdDelete write_filtersで削除できる`() { + mockMvc + .delete("/api/v2/filters/statuses/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV2FiltersStatusesIdDelete readで403`() { + mockMvc + .delete("/api/v2/filters/statuses/1") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV1FiltersGet readで取得できる`() { + mockMvc + .get("/api/v1/filters") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1FiltersGet read_filtersで取得できる`() { + mockMvc + .get("/api/v1/filters") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1FiltersGet writeで403`() { + mockMvc + .get("/api/v1/filters") { + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV1FiltersPost writeで新規作成`() { + mockMvc + .post("/api/v1/filters") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper().writeValueAsString( + V1FilterPostRequest( + phrase = "hoge", + context = listOf(V1FilterPostRequest.Context.home), + irreversible = false, + wholeWord = false, + expiresIn = null + ) + ) + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1FiltersPost write_filtersで新規作成`() { + mockMvc + .post("/api/v1/filters") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper().writeValueAsString( + V1FilterPostRequest( + phrase = "hoge", + context = listOf(V1FilterPostRequest.Context.home), + irreversible = false, + wholeWord = false, + expiresIn = null + ) + ) + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1FiltersPost readで403`() { + mockMvc + .post("/api/v1/filters") { + contentType = MediaType.APPLICATION_JSON + content = objectMapper().writeValueAsString( + V1FilterPostRequest( + phrase = "hoge", + context = listOf(V1FilterPostRequest.Context.home), + irreversible = false, + wholeWord = false, + expiresIn = null + ) + ) + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV1FiltersIdGet readで取得できる`() { + mockMvc + .get("/api/v1/filters/1") { + with( + jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1FiltersIdGet read_filtersで取得できる`() { + mockMvc + .get("/api/v1/filters/1") { + with( + jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1FiltersIdGet writeで403`() { + mockMvc + .get("/api/v1/filters/1") { + with( + jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + fun `apiV1FiltersIdDelete writeで削除できる`() { + mockMvc + .delete("/api/v1/filters/1") { + with( + jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1FiltersIdDelete write_filtersで削除できる`() { + mockMvc + .delete("/api/v1/filters/1") { + with( + jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:filters")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1FiltersIdDelete readで403`() { + mockMvc + .delete("/api/v1/filters/1") { + with( + jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } +} \ No newline at end of file diff --git a/hideout-mastodon/src/test/kotlin/mastodon/media/MediaTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/media/MediaTest.kt new file mode 100644 index 00000000..13d2bd55 --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/mastodon/media/MediaTest.kt @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mastodon.media + +import dev.usbharu.hideout.SpringApplication +import kotlinx.coroutines.test.runTest +import org.flywaydb.core.Flyway +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.mock.web.MockMultipartFile +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers +import org.springframework.test.context.jdbc.Sql +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.multipart +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.context.WebApplicationContext + +@SpringBootTest(classes = [SpringApplication::class]) +@AutoConfigureMockMvc +@Transactional +@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +class MediaTest { + + @Autowired + private lateinit var context: WebApplicationContext + + private lateinit var mockMvc: MockMvc + + @BeforeEach + fun setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()) + .build() + } + + @Test + fun メディアをアップロードできる() = runTest { + + + mockMvc + .multipart("/api/v1/media") { + + file( + MockMultipartFile( + "file", + "400x400.png", + "image/png", + String.javaClass.classLoader.getResourceAsStream("media/400x400.png") + ) + ) + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun write_mediaスコープでメディアをアップロードできる() = runTest { + + + mockMvc + .multipart("/api/v1/media") { + + file( + MockMultipartFile( + "file", + "400x400.png", + "image/png", + String.javaClass.classLoader.getResourceAsStream("media/400x400.png") + ) + ) + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:media"))) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun 権限がないと403() = runTest { + + + mockMvc + .multipart("/api/v1/media") { + + file( + MockMultipartFile( + "file", + "400x400.png", + "image/png", + String.javaClass.classLoader.getResourceAsStream("media/400x400.png") + ) + ) + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read"))) + } + .andExpect { status { isForbidden() } } + } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } + +} diff --git a/hideout-mastodon/src/test/kotlin/mastodon/notifications/ExposedNotificationsApiPaginationTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/notifications/ExposedNotificationsApiPaginationTest.kt new file mode 100644 index 00000000..97f6f8f1 --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/mastodon/notifications/ExposedNotificationsApiPaginationTest.kt @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mastodon.notifications + +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import dev.usbharu.hideout.SpringApplication +import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.Notification +import kotlinx.coroutines.test.runTest +import org.assertj.core.api.Assertions.assertThat +import org.flywaydb.core.Flyway +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers +import org.springframework.test.context.jdbc.Sql +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.get +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.context.WebApplicationContext + +@SpringBootTest(classes = [SpringApplication::class], properties = ["hideout.use-mongodb=false"]) +@AutoConfigureMockMvc +@Transactional +@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +//@Sql("/sql/notification/test-notifications.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +//@Sql("/sql/notification/test-mastodon_notifications.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +class ExposedNotificationsApiPaginationTest { + @Autowired + private lateinit var context: WebApplicationContext + + private lateinit var mockMvc: MockMvc + + @Test + fun `通知を取得できる`() = runTest { + val content = mockMvc + .get("/api/v1/notifications") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { + header { + string( + "Link", + "; rel=\"next\", ; rel=\"prev\"" + ) + } + } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + assertThat(value.first().id).isEqualTo("65") + assertThat(value.last().id).isEqualTo("26") + } + + @Test + fun maxIdを指定して通知を取得できる() = runTest { + val content = mockMvc + .get("/api/v1/notifications?max_id=26") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { + header { + string( + "Link", + "; rel=\"next\", ; rel=\"prev\"" + ) + } + } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + assertThat(value.first().id).isEqualTo("25") + assertThat(value.last().id).isEqualTo("1") + + } + + @Test + fun minIdを指定して通知を取得できる() = runTest { + val content = mockMvc + .get("/api/v1/notifications?min_id=25") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { + header { + string( + "Link", + "; rel=\"next\", ; rel=\"prev\"" + ) + } + } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + assertThat(value.first().id).isEqualTo("65") + assertThat(value.last().id).isEqualTo("26") + } + + @Test + fun 結果が0件のときはページネーションのヘッダーがない() = runTest { + val content = mockMvc + .get("/api/v1/notifications?max_id=1") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { + header { + doesNotExist("Link") + } + } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + assertThat(value).size().isZero() + } + + @BeforeEach + fun setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()) + .build() + } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } +} \ No newline at end of file diff --git a/hideout-mastodon/src/test/kotlin/mastodon/notifications/MongodbNotificationsApiPaginationTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/notifications/MongodbNotificationsApiPaginationTest.kt new file mode 100644 index 00000000..c0debcd5 --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/mastodon/notifications/MongodbNotificationsApiPaginationTest.kt @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mastodon.notifications + +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import dev.usbharu.hideout.SpringApplication +import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.Notification +import kotlinx.coroutines.test.runTest +import org.assertj.core.api.Assertions +import org.flywaydb.core.Flyway +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers +import org.springframework.test.context.jdbc.Sql +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.get +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.context.WebApplicationContext + +@SpringBootTest(classes = [SpringApplication::class], properties = ["hideout.use-mongodb=true"]) +@AutoConfigureMockMvc +@Transactional +@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +//@Sql("/sql/notification/test-notifications.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +class MongodbNotificationsApiPaginationTest { + @Autowired + private lateinit var context: WebApplicationContext + + private lateinit var mockMvc: MockMvc + + @Test + fun `通知を取得できる`() = runTest { + val content = mockMvc + .get("/api/v1/notifications") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andDo { print() } + .andExpect { + header { + string( + "Link", + "; rel=\"next\", ; rel=\"prev\"" + ) + } + } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + Assertions.assertThat(value.first().id).isEqualTo("65") + Assertions.assertThat(value.last().id).isEqualTo("26") + } + + @Test + fun maxIdを指定して通知を取得できる() = runTest { + val content = mockMvc + .get("/api/v1/notifications?max_id=26") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { + header { + string( + "Link", + "; rel=\"next\", ; rel=\"prev\"" + ) + } + } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + Assertions.assertThat(value.first().id).isEqualTo("25") + Assertions.assertThat(value.last().id).isEqualTo("1") + + } + + @Test + fun minIdを指定して通知を取得できる() = runTest { + val content = mockMvc + .get("/api/v1/notifications?min_id=25") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { + header { + string( + "Link", + "; rel=\"next\", ; rel=\"prev\"" + ) + } + } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + Assertions.assertThat(value.first().id).isEqualTo("65") + Assertions.assertThat(value.last().id).isEqualTo("26") + } + + @Test + fun 結果が0件のときはページネーションのヘッダーがない() = runTest { + val content = mockMvc + .get("/api/v1/notifications?max_id=1") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { + header { + doesNotExist("Link") + } + } + .andReturn() + .response + .contentAsString + + val value = jacksonObjectMapper().readValue(content, object : TypeReference>() {}) + + Assertions.assertThat(value).size().isZero() + } + + @BeforeEach + fun setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()) + .build() + } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } +} \ No newline at end of file diff --git a/hideout-mastodon/src/test/kotlin/mastodon/status/StatusTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/status/StatusTest.kt new file mode 100644 index 00000000..790c3cc6 --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/mastodon/status/StatusTest.kt @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mastodon.status + +import dev.usbharu.hideout.SpringApplication +import dev.usbharu.hideout.core.domain.model.emoji.UnicodeEmoji +import dev.usbharu.hideout.core.infrastructure.exposedrepository.CustomEmojis +import dev.usbharu.hideout.core.infrastructure.exposedrepository.Reactions +import dev.usbharu.hideout.core.infrastructure.exposedrepository.toReaction +import org.assertj.core.api.Assertions.assertThat +import org.flywaydb.core.Flyway +import org.jetbrains.exposed.sql.and +import org.jetbrains.exposed.sql.selectAll +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.http.MediaType +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.test.context.support.WithAnonymousUser +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers +import org.springframework.test.context.jdbc.Sql +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.post +import org.springframework.test.web.servlet.put +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.context.WebApplicationContext + +@SpringBootTest(classes = [SpringApplication::class]) +@AutoConfigureMockMvc +@Transactional +@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +@Sql("/sql/posts.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +@Sql("/sql/test-custom-emoji.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +class StatusTest { + + @Autowired + private lateinit var context: WebApplicationContext + + private lateinit var mockMvc: MockMvc + + + @BeforeEach + fun setUp() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()) + .build() + } + + @Test + fun 投稿できる() { + mockMvc + .post("/api/v1/statuses") { + contentType = MediaType.APPLICATION_JSON + content = """{"status":"hello"}""" + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun write_statusesスコープで投稿できる() { + mockMvc + .post("/api/v1/statuses") { + contentType = MediaType.APPLICATION_JSON + content = """{"status":"hello"}""" + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:statuses")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun 権限がないと403() { + mockMvc + .post("/api/v1/statuses") { + contentType = MediaType.APPLICATION_JSON + content = """{"status":"hello"}""" + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .andExpect { status { isForbidden() } } + } + + @Test + @WithAnonymousUser + fun 匿名だと401() { + mockMvc + .post("/api/v1/statuses") { + contentType = MediaType.APPLICATION_JSON + content = """{"status":"hello"}""" + with(csrf()) + } + .andExpect { status { isUnauthorized() } } + } + + @Test + @WithAnonymousUser + fun 匿名の場合通常はcsrfが無いので403() { + mockMvc + .post("/api/v1/statuses") { + contentType = MediaType.APPLICATION_JSON + content = """{"status":"hello"}""" + } + .andExpect { status { isForbidden() } } + } + + @Test + fun formでも投稿できる() { + mockMvc + .post("/api/v1/statuses") { + contentType = MediaType.APPLICATION_FORM_URLENCODED + param("status", "hello") + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write:statuses")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun in_reply_to_idを指定したら返信として処理される() { + mockMvc + .post("/api/v1/statuses") { + contentType = MediaType.APPLICATION_JSON + //language=JSON + content = """{ + "status": "hello", + "in_reply_to_id": "1" +}""" + with( + jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + ) + } + .asyncDispatch() + .andDo { print() } + .andExpect { status { isOk() } } + .andExpect { jsonPath("\$.in_reply_to_id") { value("1") } } + } + + @Test + fun ユニコード絵文字をリアクションできる() { + mockMvc + .put("/api/v1/statuses/1/emoji_reactions/😭") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .andDo { print() } + .asyncDispatch() + .andExpect { status { isOk() } } + + val reaction = + Reactions.selectAll().where { Reactions.postId eq 1 and (Reactions.actorId eq 1) }.single().toReaction() + assertThat(reaction.unicodeEmoji).isEqualTo(UnicodeEmoji("😭")) + assertThat(reaction.postId).isEqualTo(1) + assertThat(reaction.actorId).isEqualTo(1) + } + + @Test + fun 存在しない絵文字はフォールバックされる() { + mockMvc + .put("/api/v1/statuses/1/emoji_reactions/hoge") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .andDo { print() } + .asyncDispatch() + .andExpect { status { isOk() } } + + val reaction = + Reactions.selectAll().where { Reactions.postId eq 1 and (Reactions.actorId eq 1) }.single().toReaction() + assertThat(reaction.unicodeEmoji).isEqualTo(UnicodeEmoji("❤")) + assertThat(reaction.postId).isEqualTo(1) + assertThat(reaction.actorId).isEqualTo(1) + } + + @Test + fun カスタム絵文字をリアクションできる() { + mockMvc + .put("/api/v1/statuses/1/emoji_reactions/kotlin") { + with(jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write"))) + } + .andDo { print() } + .asyncDispatch() + .andExpect { status { isOk() } } + + val reaction = + Reactions.leftJoin(CustomEmojis).selectAll().where { Reactions.postId eq 1 and (Reactions.actorId eq 1) } + .single() + .toReaction() + + } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } +} diff --git a/hideout-mastodon/src/test/kotlin/mastodon/timelines/TimelineApiTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/timelines/TimelineApiTest.kt new file mode 100644 index 00000000..4d20bcfb --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/mastodon/timelines/TimelineApiTest.kt @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package mastodon.timelines + +import dev.usbharu.hideout.SpringApplication +import org.flywaydb.core.Flyway +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.test.context.support.WithAnonymousUser +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers +import org.springframework.test.context.jdbc.Sql +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.get +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.context.WebApplicationContext + +@SpringBootTest(classes = [SpringApplication::class]) +@Transactional +@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +class TimelineApiTest { + @Autowired + private lateinit var context: WebApplicationContext + + private lateinit var mockMvc: MockMvc + + @BeforeEach + fun beforeEach() { + mockMvc = MockMvcBuilders.webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()) + .build() + } + + @Test + fun `apiV1TimelinesHomeGetにreadでアクセスできる`() { + mockMvc + .get("/api/v1/timelines/home") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1TimelinesHomeGetにread statusesでアクセスできる`() { + mockMvc + .get("/api/v1/timelines/home") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:statuses")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + @WithAnonymousUser + fun apiV1TimelineHomeGetに匿名でアクセスすると401() { + mockMvc + .get("/api/v1/timelines/home") + .andExpect { status { isUnauthorized() } } + } + + @Test + fun apiV1TimelinesPublicGetにreadでアクセスできる() { + mockMvc + .get("/api/v1/timelines/public") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + fun `apiV1TimelinesPublicGetにread statusesでアクセスできる`() { + mockMvc + .get("/api/v1/timelines/public") { + with( + SecurityMockMvcRequestPostProcessors.jwt() + .jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read:statuses")) + ) + } + .asyncDispatch() + .andExpect { status { isOk() } } + } + + @Test + @WithAnonymousUser + fun apiV1TimeinesPublicGetに匿名でアクセスできる() { + mockMvc + .get("/api/v1/timelines/public") + .asyncDispatch() + .andExpect { status { isOk() } } + } + + companion object { + @JvmStatic + @AfterAll + fun dropDatabase(@Autowired flyway: Flyway) { + flyway.clean() + flyway.migrate() + } + } +} diff --git a/hideout-mastodon/src/test/kotlin/util/Json.kt b/hideout-mastodon/src/test/kotlin/util/Json.kt new file mode 100644 index 00000000..fe49c2ca --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/util/Json.kt @@ -0,0 +1,8 @@ +package util + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper + +fun objectMapper(): ObjectMapper { + return jacksonObjectMapper() +} \ No newline at end of file diff --git a/hideout-mastodon/src/test/kotlin/util/SpringApplicationTestBase.kt b/hideout-mastodon/src/test/kotlin/util/SpringApplicationTestBase.kt new file mode 100644 index 00000000..158f8c7a --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/util/SpringApplicationTestBase.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util + +import org.springframework.boot.test.context.SpringBootTest + +@SpringBootTest +abstract class SpringApplicationTestBase diff --git a/hideout-mastodon/src/test/kotlin/util/TestTransaction.kt b/hideout-mastodon/src/test/kotlin/util/TestTransaction.kt new file mode 100644 index 00000000..8830ba4e --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/util/TestTransaction.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util + +import dev.usbharu.hideout.core.application.shared.Transaction + + +object TestTransaction : Transaction { + override suspend fun transaction(block: suspend () -> T): T = block() + + override suspend fun transaction(transactionLevel: Int, block: suspend () -> T): T = block() +} diff --git a/hideout-mastodon/src/test/kotlin/util/WithHttpSignature.kt b/hideout-mastodon/src/test/kotlin/util/WithHttpSignature.kt new file mode 100644 index 00000000..d7e58abc --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/util/WithHttpSignature.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util + +//@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE) +//@Retention(AnnotationRetention.RUNTIME) +//@Inherited +//@MustBeDocumented +//@WithSecurityContext(factory = WithHttpSignatureSecurityContextFactory::class) +//annotation class WithHttpSignature( +// @get:AliasFor( +// annotation = WithSecurityContext::class +// ) val setupBefore: TestExecutionEvent = TestExecutionEvent.TEST_METHOD, +// val keyId: String = "https://example.com/users/test-user#pubkey", +// val url: String = "https://example.com/inbox", +// val method: String = "GET" +//) diff --git a/hideout-mastodon/src/test/kotlin/util/WithHttpSignatureSecurityContextFactory.kt b/hideout-mastodon/src/test/kotlin/util/WithHttpSignatureSecurityContextFactory.kt new file mode 100644 index 00000000..626cf79e --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/util/WithHttpSignatureSecurityContextFactory.kt @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util + +//class WithHttpSignatureSecurityContextFactory( +// private val actorRepository: ActorRepository, +// private val transaction: Transaction +//) : WithSecurityContextFactory { +// +// private val securityContextStrategy = SecurityContextHolder.getContextHolderStrategy() +// +// override fun createSecurityContext(annotation: WithHttpSignature): SecurityContext = runBlocking { +// val preAuthenticatedAuthenticationToken = PreAuthenticatedAuthenticationToken( +// annotation.keyId, HttpRequest( +// URL("https://example.com/inbox"), +// HttpHeaders(mapOf()), HttpMethod.GET +// ) +// ) +// val httpSignatureUser = transaction.transaction { +// val findByKeyId = +// actorRepository.findByKeyId(annotation.keyId) ?: throw IllegalArgumentException(annotation.keyId) +// HttpSignatureUser( +// findByKeyId.name, +// findByKeyId.domain, +// findByKeyId.id, +// true, +// true, +// mutableListOf() +// ) +// } +// preAuthenticatedAuthenticationToken.details = httpSignatureUser +// preAuthenticatedAuthenticationToken.isAuthenticated = true +// val emptyContext = securityContextStrategy.createEmptyContext() +// emptyContext.authentication = preAuthenticatedAuthenticationToken +// return@runBlocking emptyContext +// } +// +//} diff --git a/hideout-mastodon/src/test/kotlin/util/WithMockHttpSignature.kt b/hideout-mastodon/src/test/kotlin/util/WithMockHttpSignature.kt new file mode 100644 index 00000000..fcaba839 --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/util/WithMockHttpSignature.kt @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util + +// +//@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE) +//@Retention(AnnotationRetention.RUNTIME) +//@Inherited +//@MustBeDocumented +//@WithSecurityContext(factory = WithMockHttpSignatureSecurityContextFactory::class) +//annotation class WithMockHttpSignature( +// @get:AliasFor( +// annotation = WithSecurityContext::class +// ) val setupBefore: TestExecutionEvent = TestExecutionEvent.TEST_METHOD, +// val username: String = "test-user", +// val domain: String = "example.com", +// val keyId: String = "https://example.com/users/test-user#pubkey", +// val id: Long = 1234L, +// val url: String = "https://example.com/inbox", +// val method: String = "GET" +//) diff --git a/hideout-mastodon/src/test/kotlin/util/WithMockHttpSignatureSecurityContextFactory.kt b/hideout-mastodon/src/test/kotlin/util/WithMockHttpSignatureSecurityContextFactory.kt new file mode 100644 index 00000000..bf5218f6 --- /dev/null +++ b/hideout-mastodon/src/test/kotlin/util/WithMockHttpSignatureSecurityContextFactory.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2024 usbharu + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package util +// +//import dev.usbharu.hideout.core.infrastructure.springframework.httpsignature.HttpSignatureUser +//import dev.usbharu.httpsignature.common.HttpHeaders +//import dev.usbharu.httpsignature.common.HttpMethod +//import dev.usbharu.httpsignature.common.HttpRequest +//import org.springframework.security.core.context.SecurityContext +//import org.springframework.security.core.context.SecurityContextHolder +//import org.springframework.security.test.context.support.WithSecurityContextFactory +//import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken +//import java.net.URL +// +//class WithMockHttpSignatureSecurityContextFactory : +// WithSecurityContextFactory { +// +// private val securityContextStrategy = SecurityContextHolder.getContextHolderStrategy() +// +// override fun createSecurityContext(annotation: WithMockHttpSignature): SecurityContext { +// val preAuthenticatedAuthenticationToken = PreAuthenticatedAuthenticationToken( +// annotation.keyId, HttpRequest( +// URL(annotation.url), +// HttpHeaders(mapOf()), HttpMethod.valueOf(annotation.method.uppercase()) +// ) +// ) +// val httpSignatureUser = HttpSignatureUser( +// annotation.username, +// annotation.domain, +// annotation.id, +// true, +// true, +// mutableListOf() +// ) +// preAuthenticatedAuthenticationToken.details = httpSignatureUser +// preAuthenticatedAuthenticationToken.isAuthenticated = true +// val emptyContext = securityContextStrategy.createEmptyContext() +// emptyContext.authentication = preAuthenticatedAuthenticationToken +// return emptyContext +// } +//} diff --git a/hideout-mastodon/src/test/resources/application.yml b/hideout-mastodon/src/test/resources/application.yml index 05671a3f..0f4fd0e1 100644 --- a/hideout-mastodon/src/test/resources/application.yml +++ b/hideout-mastodon/src/test/resources/application.yml @@ -2,6 +2,8 @@ spring: datasource: url: "jdbc:h2:mem:test;MODE=POSTGRESQL;DB_CLOSE_DELAY=-1;CASE_INSENSITIVE_IDENTIFIERS=true;TRACE_LEVEL_FILE=4;" driver-class-name: org.h2.Driver + flyway: + clean-disabled: false hideout: url: "https://test-hideout-dev.usbharu.dev" security: @@ -9,4 +11,4 @@ hideout: generate: true key-id: a private-key: "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7VJTUt9Us8cKjMzEfYyjiWA4R4/M2bS1GB4t7NXp98C3SC6dVMvDuictGeurT8jNbvJZHtCSuYEvuNMoSfm76oqFvAp8Gy0iz5sxjZmSnXyCdPEovGhLa0VzMaQ8s+CLOyS56YyCFGeJZqgtzJ6GR3eqoYSW9b9UMvkBpZODSctWSNGj3P7jRFDO5VoTwCQAWbFnOjDfH5Ulgp2PKSQnSJP3AJLQNFNe7br1XbrhV//eO+t51mIpGSDCUv3E0DDFcWDTH9cXDTTlRZVEiR2BwpZOOkE/Z0/BVnhZYL71oZV34bKfWjQIt6V/isSMahdsAASACp4ZTGtwiVuNd9tybAgMBAAECggEBAKTmjaS6tkK8BlPXClTQ2vpz/N6uxDeS35mXpqasqskVlaAidgg/sWqpjXDbXr93otIMLlWsM+X0CqMDgSXKejLS2jx4GDjI1ZTXg++0AMJ8sJ74pWzVDOfmCEQ/7wXs3+cbnXhKriO8Z036q92Qc1+N87SI38nkGa0ABH9CN83HmQqt4fB7UdHzuIRe/me2PGhIq5ZBzj6h3BpoPGzEP+x3l9YmK8t/1cN0pqI+dQwYdgfGjackLu/2qH80MCF7IyQaseZUOJyKrCLtSD/Iixv/hzDEUPfOCjFDgTpzf3cwta8+oE4wHCo1iI1/4TlPkwmXx4qSXtmw4aQPz7IDQvECgYEA8KNThCO2gsC2I9PQDM/8Cw0O983WCDY+oi+7JPiNAJwv5DYBqEZB1QYdj06YD16XlC/HAZMsMku1na2TN0driwenQQWzoev3g2S7gRDoS/FCJSI3jJ+kjgtaA7Qmzlgk1TxODN+G1H91HW7t0l7VnL27IWyYo2qRRK3jzxqUiPUCgYEAx0oQs2reBQGMVZnApD1jeq7n4MvNLcPvt8b/eU9iUv6Y4Mj0Suo/AU8lYZXm8ubbqAlwz2VSVunD2tOplHyMUrtCtObAfVDUAhCndKaA9gApgfb3xw1IKbuQ1u4IF1FJl3VtumfQn//LiH1B3rXhcdyo3/vIttEk48RakUKClU8CgYEAzV7W3COOlDDcQd935DdtKBFRAPRPAlspQUnzMi5eSHMD/ISLDY5IiQHbIH83D4bvXq0X7qQoSBSNP7Dvv3HYuqMhf0DaegrlBuJllFVVq9qPVRnKxt1Il2HgxOBvbhOT+9in1BzA+YJ99UzC85O0Qz06A+CmtHEy4aZ2kj5hHjECgYEAmNS4+A8Fkss8Js1RieK2LniBxMgmYml3pfVLKGnzmng7H2+cwPLhPIzIuwytXywh2bzbsYEfYx3EoEVgMEpPhoarQnYPukrJO4gwE2o5Te6T5mJSZGlQJQj9q4ZB2Dfzet6INsK0oG8XVGXSpQvQh3RUYekCZQkBBFcpqWpbIEsCgYAnM3DQf3FJoSnXaMhrVBIovic5l0xFkEHskAjFTevO86Fsz1C2aSeRKSqGFoOQ0tmJzBEs1R6KqnHInicDTQrKhArgLXX4v3CddjfTRJkFWDbE/CkvKZNOrcf1nhaGCPspRJj2KUkj1Fhl9Cncdn/RsYEONbwQSjIfMPkvxF+8HQ==" - public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u+qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmwIDAQAB" \ No newline at end of file + public-key: "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u+qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmwIDAQAB" diff --git a/hideout-mastodon/src/test/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql b/hideout-mastodon/src/test/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql new file mode 100644 index 00000000..a2b01c22 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/accounts/apiV1AccountsIdFollowPost フォローできる.sql @@ -0,0 +1,17 @@ +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) +VALUES (3733363, 'follow-test-user-1', 'example.com', 'follow-test-user-1-name', '', + 'https://example.com/users/follow-test-user-1/inbox', + 'https://example.com/users/follow-test-user-1/outbox', 'https://example.com/users/follow-test-user-1', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/follow-test-user-1#pubkey', 'https://example.com/users/follow-test-user-1/following', + 'https://example.com/users/follow-test-user-1/followers', 0, false, 0, 0, 0, null), + (37335363, 'follow-test-user-2', 'example.com', 'follow-test-user-2-name', '', + 'https://example.com/users/follow-test-user-2/inbox', + 'https://example.com/users/follow-test-user-2/outbox', 'https://example.com/users/follow-test-user-2', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/follow-test-user-2#pubkey', 'https://example.com/users/follow-test-user-2/following', + 'https://example.com/users/follow-test-user-2/followers', 0, false, 0, 0, 0, null); diff --git a/hideout-mastodon/src/test/resources/sql/accounts/test-accounts-statuses.sql b/hideout-mastodon/src/test/resources/sql/accounts/test-accounts-statuses.sql new file mode 100644 index 00000000..058a3e81 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/accounts/test-accounts-statuses.sql @@ -0,0 +1,201 @@ +insert into posts (id, actor_id, instance_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, deleted, hide, move_to) +VALUES (1, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/1', + null, null, false, 'https://example.com/users/1/posts/1', false,false,null), + (2, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/2', + null, 1, false, 'https://example.com/users/1/posts/2', false,false,null), + (3, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/3', + null, null, false, 'https://example.com/users/1/posts/3', false,false,null), + (4, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/4', + null, 3, false, 'https://example.com/users/1/posts/4', false,false,null), + (5, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/5', + null, null, false, 'https://example.com/users/1/posts/5', false,false,null), + (6, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/6', + null, null, false, 'https://example.com/users/1/posts/6', false,false,null), + (7, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/7', + null, null, false, 'https://example.com/users/1/posts/7', false,false,null), + (8, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/8', + null, 7, false, 'https://example.com/users/1/posts/8', false,false,null), + (9, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/9', + null, null, false, 'https://example.com/users/1/posts/9', false,false,null), + (10, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/10', + null, 9, false, 'https://example.com/users/1/posts/10', false,false,null), + (11, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/11', + null, null, false, 'https://example.com/users/1/posts/11', false,false,null), + (12, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/12', + null, null, false, 'https://example.com/users/1/posts/12', false,false,null), + (13, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/13', + null, null, false, 'https://example.com/users/1/posts/13', false,false,null), + (14, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/14', + null, 13, false, 'https://example.com/users/1/posts/14', false,false,null), + (15, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/15', + null, null, false, 'https://example.com/users/1/posts/15', false,false,null), + (16, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/16', + null, 15, false, 'https://example.com/users/1/posts/16', false,false,null), + (17, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/17', + null, null, false, 'https://example.com/users/1/posts/17', false,false,null), + (18, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/18', + null, null, false, 'https://example.com/users/1/posts/18', false,false,null), + (19, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/19', + null, null, false, 'https://example.com/users/1/posts/19', false,false,null), + (20, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/20', + null, 19, false, 'https://example.com/users/1/posts/20', false,false,null), + (21, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/21', + null, null, false, 'https://example.com/users/1/posts/21', false,false,null), + (22, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/22', + null, 21, false, 'https://example.com/users/1/posts/22', false,false,null), + (23, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/23', + null, null, false, 'https://example.com/users/1/posts/23', false,false,null), + (24, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/24', + null, null, false, 'https://example.com/users/1/posts/24', false,false,null), + (25, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/25', + null, null, false, 'https://example.com/users/1/posts/25', false,false,null), + (26, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/26', + null, 25, false, 'https://example.com/users/1/posts/26', false,false,null), + (27, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/27', + null, null, false, 'https://example.com/users/1/posts/27', false,false,null), + (28, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/28', + null, 27, false, 'https://example.com/users/1/posts/28', false,false,null), + (29, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/29', + null, null, false, 'https://example.com/users/1/posts/29', false,false,null), + (30, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/30', + null, null, false, 'https://example.com/users/1/posts/30', false,false,null), + (31, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/31', + null, null, false, 'https://example.com/users/1/posts/31', false,false,null), + (32, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/32', + null, 31, false, 'https://example.com/users/1/posts/32', false,false,null), + (33, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/33', + null, null, false, 'https://example.com/users/1/posts/33', false,false,null), + (34, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/34', + null, 33, false, 'https://example.com/users/1/posts/34', false,false,null), + (35, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/35', + null, null, false, 'https://example.com/users/1/posts/35', false,false,null), + (36, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/36', + null, null, false, 'https://example.com/users/1/posts/36', false,false,null), + (37, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/37', + null, null, false, 'https://example.com/users/1/posts/37', false,false,null), + (38, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/38', + null, 37, false, 'https://example.com/users/1/posts/38', false,false,null), + (39, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/39', + null, null, false, 'https://example.com/users/1/posts/39', false,false,null), + (40, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/40', + null, 39, false, 'https://example.com/users/1/posts/40', false,false,null), + (41, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/41', + null, null, false, 'https://example.com/users/1/posts/41', false,false,null), + (42, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/42', + null, null, false, 'https://example.com/users/1/posts/42', false,false,null), + (43, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/43', + null, null, false, 'https://example.com/users/1/posts/43', false,false,null), + (44, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/44', + null, 43, false, 'https://example.com/users/1/posts/44', false,false,null), + (45, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/45', + null, null, false, 'https://example.com/users/1/posts/45', false,false,null), + (46, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/46', + null, 45, false, 'https://example.com/users/1/posts/46', false,false,null), + (47, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/47', + null, null, false, 'https://example.com/users/1/posts/47', false,false,null), + (48, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/48', + null, null, false, 'https://example.com/users/1/posts/48', false,false,null), + (49, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/49', + null, null, false, 'https://example.com/users/1/posts/49', false,false,null), + (50, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/50', + null, 49, false, 'https://example.com/users/1/posts/50', false,false,null), + (51, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/51', + null, null, false, 'https://example.com/users/1/posts/51', false,false,null), + (52, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/52', + null, 51, false, 'https://example.com/users/1/posts/52', false,false,null), + (53, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/53', + null, null, false, 'https://example.com/users/1/posts/53', false,false,null), + (54, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/54', + null, null, false, 'https://example.com/users/1/posts/54', false,false,null), + (55, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/55', + null, null, false, 'https://example.com/users/1/posts/55', false,false,null), + (56, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/56', + null, 55, false, 'https://example.com/users/1/posts/56', false,false,null), + (57, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/57', + null, null, false, 'https://example.com/users/1/posts/57', false,false,null), + (58, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/58', + null, 57, false, 'https://example.com/users/1/posts/58', false,false,null), + (59, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/59', + null, null, false, 'https://example.com/users/1/posts/59', false,false,null), + (60, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/60', + null, null, false, 'https://example.com/users/1/posts/60', false,false,null), + (61, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/61', + null, null, false, 'https://example.com/users/1/posts/61', false,false,null), + (62, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/62', + null, 61, false, 'https://example.com/users/1/posts/62', false,false,null), + (63, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/63', + null, null, false, 'https://example.com/users/1/posts/63', false,false,null), + (64, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/64', + null, 63, false, 'https://example.com/users/1/posts/64', false,false,null), + (65, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/65', + null, null, false, 'https://example.com/users/1/posts/65', false,false,null), + (66, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/66', + null, null, false, 'https://example.com/users/1/posts/66', false,false,null), + (67, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/67', + null, null, false, 'https://example.com/users/1/posts/67', false,false,null), + (68, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/68', + null, 67, false, 'https://example.com/users/1/posts/68', false,false,null), + (69, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/69', + null, null, false, 'https://example.com/users/1/posts/69', false,false,null), + (70, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/70', + null, 69, false, 'https://example.com/users/1/posts/70', false,false,null), + (71, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/71', + null, null, false, 'https://example.com/users/1/posts/71', false,false,null), + (72, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/72', + null, null, false, 'https://example.com/users/1/posts/72', false,false,null), + (73, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/73', + null, null, false, 'https://example.com/users/1/posts/73', false,false,null), + (74, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/74', + null, 73, false, 'https://example.com/users/1/posts/74', false,false,null), + (75, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/75', + null, null, false, 'https://example.com/users/1/posts/75', false,false,null), + (76, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/76', + null, 75, false, 'https://example.com/users/1/posts/76', false,false,null), + (77, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/77', + null, null, false, 'https://example.com/users/1/posts/77', false,false,null), + (78, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/78', + null, null, false, 'https://example.com/users/1/posts/78', false,false,null), + (79, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/79', + null, null, false, 'https://example.com/users/1/posts/79', false,false,null), + (80, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/80', + null, 79, false, 'https://example.com/users/1/posts/80', false,false,null), + (81, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/81', + null, null, false, 'https://example.com/users/1/posts/81', false,false,null), + (82, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/82', + null, 81, false, 'https://example.com/users/1/posts/82', false,false,null), + (83, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/83', + null, null, false, 'https://example.com/users/1/posts/83', false,false,null), + (84, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/84', + null, null, false, 'https://example.com/users/1/posts/84', false,false,null), + (85, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/85', + null, null, false, 'https://example.com/users/1/posts/85', false,false,null), + (86, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/86', + null, 85, false, 'https://example.com/users/1/posts/86', false,false,null), + (87, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/87', + null, null, false, 'https://example.com/users/1/posts/87', false,false,null), + (88, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/88', + null, 87, false, 'https://example.com/users/1/posts/88', false,false,null), + (89, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/89', + null, null, false, 'https://example.com/users/1/posts/89', false,false,null), + (90, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/90', + null, null, false, 'https://example.com/users/1/posts/90', false,false,null), + (91, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/91', + null, null, false, 'https://example.com/users/1/posts/91', false,false,null), + (92, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/92', + null, 91, false, 'https://example.com/users/1/posts/92', false,false,null), + (93, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/93', + null, null, false, 'https://example.com/users/1/posts/93', false,false,null), + (94, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/94', + null, 93, false, 'https://example.com/users/1/posts/94', false,false,null), + (95, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/95', + null, null, false, 'https://example.com/users/1/posts/95', false,false,null), + (96, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/96', + null, null, false, 'https://example.com/users/1/posts/96', false,false,null), + (97, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/97', + null, null, false, 'https://example.com/users/1/posts/97', false,false,null), + (98, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/98', + null, 97, false, 'https://example.com/users/1/posts/98', false,false,null), + (99, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'FOLLOWERS', 'https://example.com/users/1/posts/99', + null, null, false, 'https://example.com/users/1/posts/99', false,false,null), + (100, 1,1,null, '

this is test

', 'this is test', current_timestamp, 'PUBLIC', 'https://example.com/users/1/posts/100', + null, 99, false, 'https://example.com/users/1/posts/100', false,false,null); \ No newline at end of file diff --git a/hideout-mastodon/src/test/resources/sql/filter/test-filter.sql b/hideout-mastodon/src/test/resources/sql/filter/test-filter.sql new file mode 100644 index 00000000..d06d6bc0 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/filter/test-filter.sql @@ -0,0 +1,4 @@ +insert into filters (id, user_id, name, context, action) +VALUES (1, 1, 'test filter', 'home', 'warn'); +insert into filter_keywords(id, filter_id, keyword, mode) +VALUES (1, 1, 'hoge', 'NONE') \ No newline at end of file diff --git a/hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql b/hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql new file mode 100644 index 00000000..dc2ab9f1 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがfollowers投稿を取得できる.sql @@ -0,0 +1,28 @@ +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) +VALUES (8, 'test-user8', 'example.com', 'Im test-user8.', 'THis account is test-user8.', + 'https://example.com/users/test-user8/inbox', + 'https://example.com/users/test-user8/outbox', 'https://example.com/users/test-user8', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user8#pubkey', 'https://example.com/users/test-user8/following', + 'https://example.com/users/test-user8/followers', 0, false, 0, 0, 0, null), + (9, 'test-user9', 'follower.example.com', 'Im test-user9.', 'THis account is test-user9.', + 'https://follower.example.com/users/test-user9/inbox', + 'https://follower.example.com/users/test-user9/outbox', 'https://follower.example.com/users/test-user9', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + null, 12345678, + 'https://follower.example.com/users/test-user9#pubkey', + 'https://follower.example.com/users/test-user9/following', + 'https://follower.example.com/users/test-user9/followers', 0, false, 0, 0, 0, null); + +insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, + ignore_follow_request) +VALUES (9, 8, true, false, false, false, false); + +insert into POSTS (ID, ACTOR_ID, OVERVIEW, CONTENT, TEXT, CREATED_AT, VISIBILITY, URL, REPLY_ID, REPOST_ID, SENSITIVE, + AP_ID) +VALUES (1239, 8, null, '

test post

', 'test post', 12345680, 2, 'https://example.com/users/test-user8/posts/1239', + null, null, false, + 'https://example.com/users/test-user8/posts/1239'); diff --git a/hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql b/hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql new file mode 100644 index 00000000..a44861f4 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがpublic投稿を取得できる.sql @@ -0,0 +1,29 @@ +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) +VALUES (4, 'test-user4', 'example.com', 'Im test user4.', 'THis account is test user4.', + 'https://example.com/users/test-user4/inbox', + 'https://example.com/users/test-user4/outbox', 'https://example.com/users/test-user4', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user4#pubkey', 'https://example.com/users/test-user4/following', + 'https://example.com/users/test-user4/followers', 0, false, 0, 0, 0, null), + (5, 'test-user5', 'follower.example.com', 'Im test user5.', 'THis account is test user5.', + 'https://follower.example.com/users/test-user5/inbox', + 'https://follower.example.com/users/test-user5/outbox', 'https://follower.example.com/users/test-user5', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + null, 12345678, + 'https://follower.example.com/users/test-user5#pubkey', + 'https://follower.example.com/users/test-user5/following', + 'https://follower.example.com/users/test-user5/followers', 0, false, 0, 0, 0, null); + +insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, + ignore_follow_request) +VALUES (5, 4, true, false, false, false, false); + +insert into POSTS (ID, "actor_id", OVERVIEW, CONTENT, TEXT, "created_at", VISIBILITY, URL, "repost_id", "reply_id", + SENSITIVE, + AP_ID) +VALUES (1237, 4, null, '

test post

', 'test post', 12345680, 0, 'https://example.com/users/test-user4/posts/1237', + null, null, false, + 'https://example.com/users/test-user4/posts/1237'); diff --git a/hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql b/hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql new file mode 100644 index 00000000..77cb3395 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/note/httpSignature認証でフォロワーがunlisted投稿を取得できる.sql @@ -0,0 +1,29 @@ +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) +VALUES (6, 'test-user6', 'example.com', 'Im test-user6.', 'THis account is test-user6.', + 'https://example.com/users/test-user6/inbox', + 'https://example.com/users/test-user6/outbox', 'https://example.com/users/test-user6', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user6#pubkey', 'https://example.com/users/test-user6/following', + 'https://example.com/users/test-user6/followers', 0, false, 0, 0, 0, null), + (7, 'test-user7', 'follower.example.com', 'Im test-user7.', 'THis account is test-user7.', + 'https://follower.example.com/users/test-user7/inbox', + 'https://follower.example.com/users/test-user7/outbox', 'https://follower.example.com/users/test-user7', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + null, 12345678, + 'https://follower.example.com/users/test-user7#pubkey', + 'https://follower.example.com/users/test-user7/following', + 'https://follower.example.com/users/test-user7/followers', 0, false, 0, 0, 0, null); + +insert into relationships (actor_id, target_actor_id, following, blocking, muting, follow_request, + ignore_follow_request) +VALUES (7, 6, true, false, false, false, false); + +insert into POSTS (ID, "actor_ID", OVERVIEW, CONTENT, TEXT, "CREATED_AT", VISIBILITY, URL, "REPOST_ID", "REPLY_ID", + SENSITIVE, + AP_ID) +VALUES (1238, 6, null, '

test post

', 'test post', 12345680, 1, 'https://example.com/users/test-user6/posts/1238', + null, null, false, + 'https://example.com/users/test-user6/posts/1238'); diff --git a/hideout-mastodon/src/test/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql b/hideout-mastodon/src/test/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql new file mode 100644 index 00000000..6cc9db8c --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/note/メディア付き投稿はattachmentにDocumentとして画像が存在する.sql @@ -0,0 +1,25 @@ +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) +VALUES (11, 'test-user11', 'example.com', 'Im test-user11.', 'THis account is test-user11.', + 'https://example.com/users/test-user11/inbox', + 'https://example.com/users/test-user11/outbox', 'https://example.com/users/test-user11', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user11#pubkey', 'https://example.com/users/test-user11/following', + 'https://example.com/users/test-user11/followers', 0, false, 0, 0, 0, null); + +insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, + ap_id, + deleted) +VALUES (1242, 11, null, '

test post

', 'test post', 12345680, 0, + 'https://example.com/users/test-user11/posts/1242', null, null, false, + 'https://example.com/users/test-user11/posts/1242', false); + +insert into MEDIA (ID, NAME, URL, REMOTE_URL, THUMBNAIL_URL, TYPE, BLURHASH, MIME_TYPE, DESCRIPTION) +VALUES (1, 'test-media', 'https://example.com/media/test-media.png', null, null, 0, null, 'image/png', null), + (2, 'test-media2', 'https://example.com/media/test-media2.png', null, null, 0, null, 'image/png', null); + +insert into POSTS_MEDIA(POST_ID, MEDIA_ID) +VALUES (1242, 1), + (1242, 2); diff --git a/hideout-mastodon/src/test/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql b/hideout-mastodon/src/test/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql new file mode 100644 index 00000000..41ac73a4 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/note/リプライになっている投稿はinReplyToが存在する.sql @@ -0,0 +1,20 @@ +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) +VALUES (10, 'test-user10', 'example.com', 'Im test-user10.', 'THis account is test-user10.', + 'https://example.com/users/test-user10/inbox', + 'https://example.com/users/test-user10/outbox', 'https://example.com/users/test-user10', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user10#pubkey', 'https://example.com/users/test-user10/following', + 'https://example.com/users/test-user10/followers', 0, false, 0, 0, 0, null); + +insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, + ap_id, + deleted) +VALUES (1240, 10, null, '

test post

', 'test post', 12345680, 0, + 'https://example.com/users/test-user10/posts/1240', null, null, false, + 'https://example.com/users/test-user10/posts/1240', false), + (1241, 10, null, '

test post

', 'test post', 12345680, 0, + 'https://example.com/users/test-user10/posts/1241', null, 1240, false, + 'https://example.com/users/test-user10/posts/1241', false); diff --git a/hideout-mastodon/src/test/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql b/hideout-mastodon/src/test/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql new file mode 100644 index 00000000..250cfb5a --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/note/匿名でfollowers投稿を取得しようとすると404.sql @@ -0,0 +1,17 @@ +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) +VALUES (3, 'test-user3', 'example.com', 'Im test user3.', 'THis account is test user3.', + 'https://example.com/users/test-user3/inbox', + 'https://example.com/users/test-user3/outbox', 'https://example.com/users/test-user3', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user3#pubkey', 'https://example.com/users/test-user3/following', + 'https://example.com/users/test-user3/followers', 0, false, 0, 0, 0, null); + +insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, + ap_id, + deleted) +VALUES (1236, 3, null, '

test post

', 'test post', 12345680, 2, 'https://example.com/users/test-user3/posts/1236', + null, null, false, + 'https://example.com/users/test-user3/posts/1236', false) diff --git a/hideout-mastodon/src/test/resources/sql/note/匿名でpublic投稿を取得できる.sql b/hideout-mastodon/src/test/resources/sql/note/匿名でpublic投稿を取得できる.sql new file mode 100644 index 00000000..777f9244 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/note/匿名でpublic投稿を取得できる.sql @@ -0,0 +1,17 @@ +insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at, + key_id, following, followers, instance, locked, following_count, followers_count, posts_count, + last_post_at) +VALUES (1, 'test-user', 'example.com', 'Im test user.', 'THis account is test user.', + 'https://example.com/users/test-user/inbox', + 'https://example.com/users/test-user/outbox', 'https://example.com/users/test-user', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user#pubkey', 'https://example.com/users/test-user/following', + 'https://example.com/users/test-users/followers', 0, false, 0, 0, 0, null); + +insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, + ap_id, + deleted) +VALUES (1234, 1, null, '

test post

', 'test post', 12345680, 0, 'https://example.com/users/test-user/posts/1234', + null, null, false, + 'https://example.com/users/test-user/posts/1234', false) diff --git a/hideout-mastodon/src/test/resources/sql/note/匿名でunlisted投稿を取得できる.sql b/hideout-mastodon/src/test/resources/sql/note/匿名でunlisted投稿を取得できる.sql new file mode 100644 index 00000000..b132734d --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/note/匿名でunlisted投稿を取得できる.sql @@ -0,0 +1,17 @@ +insert into actors (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, created_at, + key_id, following, followers, instance, locked, following_count, followers_count, posts_count, + last_post_at) +VALUES (2, 'test-user2', 'example.com', 'Im test user2.', 'THis account is test user2.', + 'https://example.com/users/test-user2/inbox', + 'https://example.com/users/test-user2/outbox', 'https://example.com/users/test-user2', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user2#pubkey', 'https://example.com/users/test-user2/following', + 'https://example.com/users/test-user2/followers', 0, false, 0, 0, 0, null); + +insert into POSTS (id, actor_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, + ap_id, + deleted) +VALUES (1235, 2, null, '

test post

', 'test post', 12345680, 1, 'https://example.com/users/test-user2/posts/1235', + null, null, false, + 'https://example.com/users/test-user2/posts/1235', false) diff --git a/hideout-mastodon/src/test/resources/sql/notification/test-mastodon_notifications.sql b/hideout-mastodon/src/test/resources/sql/notification/test-mastodon_notifications.sql new file mode 100644 index 00000000..c97a25a7 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/notification/test-mastodon_notifications.sql @@ -0,0 +1,66 @@ +insert into mastodon_notifications (id, user_id, type, created_at, account_id, status_id, report_id, relationship_serverance_event_id) +values (1, 1, 'follow', current_timestamp, 2, null, null, null), + (2, 1, 'follow', current_timestamp, 2, null, null, null), + (3, 1, 'follow', current_timestamp, 2, null, null, null), + (4, 1, 'follow', current_timestamp, 2, null, null, null), + (5, 1, 'follow', current_timestamp, 2, null, null, null), + (6, 1, 'follow', current_timestamp, 2, null, null, null), + (7, 1, 'follow', current_timestamp, 2, null, null, null), + (8, 1, 'follow', current_timestamp, 2, null, null, null), + (9, 1, 'follow', current_timestamp, 2, null, null, null), + (10, 1, 'follow', current_timestamp, 2, null, null, null), + (11, 1, 'follow', current_timestamp, 2, null, null, null), + (12, 1, 'follow', current_timestamp, 2, null, null, null), + (13, 1, 'follow', current_timestamp, 2, null, null, null), + (14, 1, 'follow', current_timestamp, 2, null, null, null), + (15, 1, 'follow', current_timestamp, 2, null, null, null), + (16, 1, 'follow', current_timestamp, 2, null, null, null), + (17, 1, 'follow', current_timestamp, 2, null, null, null), + (18, 1, 'follow', current_timestamp, 2, null, null, null), + (19, 1, 'follow', current_timestamp, 2, null, null, null), + (20, 1, 'follow', current_timestamp, 2, null, null, null), + (21, 1, 'follow', current_timestamp, 2, null, null, null), + (22, 1, 'follow', current_timestamp, 2, null, null, null), + (23, 1, 'follow', current_timestamp, 2, null, null, null), + (24, 1, 'follow', current_timestamp, 2, null, null, null), + (25, 1, 'follow', current_timestamp, 2, null, null, null), + (26, 1, 'follow', current_timestamp, 2, null, null, null), + (27, 1, 'follow', current_timestamp, 2, null, null, null), + (28, 1, 'follow', current_timestamp, 2, null, null, null), + (29, 1, 'follow', current_timestamp, 2, null, null, null), + (30, 1, 'follow', current_timestamp, 2, null, null, null), + (31, 1, 'follow', current_timestamp, 2, null, null, null), + (32, 1, 'follow', current_timestamp, 2, null, null, null), + (33, 1, 'follow', current_timestamp, 2, null, null, null), + (34, 1, 'follow', current_timestamp, 2, null, null, null), + (35, 1, 'follow', current_timestamp, 2, null, null, null), + (36, 1, 'follow', current_timestamp, 2, null, null, null), + (37, 1, 'follow', current_timestamp, 2, null, null, null), + (38, 1, 'follow', current_timestamp, 2, null, null, null), + (39, 1, 'follow', current_timestamp, 2, null, null, null), + (40, 1, 'follow', current_timestamp, 2, null, null, null), + (41, 1, 'follow', current_timestamp, 2, null, null, null), + (42, 1, 'follow', current_timestamp, 2, null, null, null), + (43, 1, 'follow', current_timestamp, 2, null, null, null), + (44, 1, 'follow', current_timestamp, 2, null, null, null), + (45, 1, 'follow', current_timestamp, 2, null, null, null), + (46, 1, 'follow', current_timestamp, 2, null, null, null), + (47, 1, 'follow', current_timestamp, 2, null, null, null), + (48, 1, 'follow', current_timestamp, 2, null, null, null), + (49, 1, 'follow', current_timestamp, 2, null, null, null), + (50, 1, 'follow', current_timestamp, 2, null, null, null), + (51, 1, 'follow', current_timestamp, 2, null, null, null), + (52, 1, 'follow', current_timestamp, 2, null, null, null), + (53, 1, 'follow', current_timestamp, 2, null, null, null), + (54, 1, 'follow', current_timestamp, 2, null, null, null), + (55, 1, 'follow', current_timestamp, 2, null, null, null), + (56, 1, 'follow', current_timestamp, 2, null, null, null), + (57, 1, 'follow', current_timestamp, 2, null, null, null), + (58, 1, 'follow', current_timestamp, 2, null, null, null), + (59, 1, 'follow', current_timestamp, 2, null, null, null), + (60, 1, 'follow', current_timestamp, 2, null, null, null), + (61, 1, 'follow', current_timestamp, 2, null, null, null), + (62, 1, 'follow', current_timestamp, 2, null, null, null), + (63, 1, 'follow', current_timestamp, 2, null, null, null), + (64, 1, 'follow', current_timestamp, 2, null, null, null), + (65, 1, 'follow', current_timestamp, 2, null, null, null); \ No newline at end of file diff --git a/hideout-mastodon/src/test/resources/sql/notification/test-notifications.sql b/hideout-mastodon/src/test/resources/sql/notification/test-notifications.sql new file mode 100644 index 00000000..38982603 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/notification/test-notifications.sql @@ -0,0 +1,66 @@ +insert into notifications(id, type, user_id, source_actor_id, post_id, text, reaction_id, created_at) +VALUES (1, 'follow', 1, 2, null, null, null, current_timestamp), + (2, 'follow', 1, 2, null, null, null, current_timestamp), + (3, 'follow', 1, 2, null, null, null, current_timestamp), + (4, 'follow', 1, 2, null, null, null, current_timestamp), + (5, 'follow', 1, 2, null, null, null, current_timestamp), + (6, 'follow', 1, 2, null, null, null, current_timestamp), + (7, 'follow', 1, 2, null, null, null, current_timestamp), + (8, 'follow', 1, 2, null, null, null, current_timestamp), + (9, 'follow', 1, 2, null, null, null, current_timestamp), + (10, 'follow', 1, 2, null, null, null, current_timestamp), + (11, 'follow', 1, 2, null, null, null, current_timestamp), + (12, 'follow', 1, 2, null, null, null, current_timestamp), + (13, 'follow', 1, 2, null, null, null, current_timestamp), + (14, 'follow', 1, 2, null, null, null, current_timestamp), + (15, 'follow', 1, 2, null, null, null, current_timestamp), + (16, 'follow', 1, 2, null, null, null, current_timestamp), + (17, 'follow', 1, 2, null, null, null, current_timestamp), + (18, 'follow', 1, 2, null, null, null, current_timestamp), + (19, 'follow', 1, 2, null, null, null, current_timestamp), + (20, 'follow', 1, 2, null, null, null, current_timestamp), + (21, 'follow', 1, 2, null, null, null, current_timestamp), + (22, 'follow', 1, 2, null, null, null, current_timestamp), + (23, 'follow', 1, 2, null, null, null, current_timestamp), + (24, 'follow', 1, 2, null, null, null, current_timestamp), + (25, 'follow', 1, 2, null, null, null, current_timestamp), + (26, 'follow', 1, 2, null, null, null, current_timestamp), + (27, 'follow', 1, 2, null, null, null, current_timestamp), + (28, 'follow', 1, 2, null, null, null, current_timestamp), + (29, 'follow', 1, 2, null, null, null, current_timestamp), + (30, 'follow', 1, 2, null, null, null, current_timestamp), + (31, 'follow', 1, 2, null, null, null, current_timestamp), + (32, 'follow', 1, 2, null, null, null, current_timestamp), + (33, 'follow', 1, 2, null, null, null, current_timestamp), + (34, 'follow', 1, 2, null, null, null, current_timestamp), + (35, 'follow', 1, 2, null, null, null, current_timestamp), + (36, 'follow', 1, 2, null, null, null, current_timestamp), + (37, 'follow', 1, 2, null, null, null, current_timestamp), + (38, 'follow', 1, 2, null, null, null, current_timestamp), + (39, 'follow', 1, 2, null, null, null, current_timestamp), + (40, 'follow', 1, 2, null, null, null, current_timestamp), + (41, 'follow', 1, 2, null, null, null, current_timestamp), + (42, 'follow', 1, 2, null, null, null, current_timestamp), + (43, 'follow', 1, 2, null, null, null, current_timestamp), + (44, 'follow', 1, 2, null, null, null, current_timestamp), + (45, 'follow', 1, 2, null, null, null, current_timestamp), + (46, 'follow', 1, 2, null, null, null, current_timestamp), + (47, 'follow', 1, 2, null, null, null, current_timestamp), + (48, 'follow', 1, 2, null, null, null, current_timestamp), + (49, 'follow', 1, 2, null, null, null, current_timestamp), + (50, 'follow', 1, 2, null, null, null, current_timestamp), + (51, 'follow', 1, 2, null, null, null, current_timestamp), + (52, 'follow', 1, 2, null, null, null, current_timestamp), + (53, 'follow', 1, 2, null, null, null, current_timestamp), + (54, 'follow', 1, 2, null, null, null, current_timestamp), + (55, 'follow', 1, 2, null, null, null, current_timestamp), + (56, 'follow', 1, 2, null, null, null, current_timestamp), + (57, 'follow', 1, 2, null, null, null, current_timestamp), + (58, 'follow', 1, 2, null, null, null, current_timestamp), + (59, 'follow', 1, 2, null, null, null, current_timestamp), + (60, 'follow', 1, 2, null, null, null, current_timestamp), + (61, 'follow', 1, 2, null, null, null, current_timestamp), + (62, 'follow', 1, 2, null, null, null, current_timestamp), + (63, 'follow', 1, 2, null, null, null, current_timestamp), + (64, 'follow', 1, 2, null, null, null, current_timestamp), + (65, 'follow', 1, 2, null, null, null, current_timestamp); \ No newline at end of file diff --git a/hideout-mastodon/src/test/resources/sql/posts.sql b/hideout-mastodon/src/test/resources/sql/posts.sql index f8dec6b9..cf8c71bf 100644 --- a/hideout-mastodon/src/test/resources/sql/posts.sql +++ b/hideout-mastodon/src/test/resources/sql/posts.sql @@ -1,15 +1,15 @@ insert into posts (id, actor_id, instance_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, sensitive, ap_id, deleted, hide, move_to) values (1, 1, 1, null, 'content', 'text', current_timestamp, 'PUBLIC', 'https://example.com', null, null, false, - 'https://example.com', false, false, null), + 'https://example.com/1', false, false, null), (2, 2, 2, null, 'content', 'text', current_timestamp, 'FOLLOWERS', 'https://example.com', null, null, false, - 'https://example.com', false, false, null), + 'https://example.com/2', false, false, null), (3, 3, 1, null, 'content', 'text', current_timestamp, 'PUBLIC', 'https://example.com', null, null, false, - 'https://example.com', false, false, null), + 'https://example.com/3', false, false, null), (4, 4, 1, null, 'content', 'text', current_timestamp, 'FOLLOWERS', 'https://example.com', null, null, false, - 'https://example.com', false, false, null), + 'https://example.com/4', false, false, null), (5, 4, 1, null, 'content', 'text', current_timestamp, 'DIRECT', 'https://example.com', null, null, false, - 'https://example.com', false, false, null); + 'https://example.com/5', false, false, null); insert into posts_visible_actors(post_id, actor_id) VALUES (5, 2); \ No newline at end of file diff --git a/hideout-mastodon/src/test/resources/sql/test-custom-emoji.sql b/hideout-mastodon/src/test/resources/sql/test-custom-emoji.sql new file mode 100644 index 00000000..83c2747a --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/test-custom-emoji.sql @@ -0,0 +1,3 @@ +insert into emojis(id, name, domain, instance_id, url, category, created_at) +VALUES (1, 'kotlin', 'example.com', null, 'https://example.com/emojis/kotlin', null, + TIMESTAMP '2024-01-08 07:51:30.036Z'); diff --git a/hideout-mastodon/src/test/resources/sql/test-post.sql b/hideout-mastodon/src/test/resources/sql/test-post.sql new file mode 100644 index 00000000..da7c5343 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/test-post.sql @@ -0,0 +1,4 @@ +insert into posts (id, actor_id, instance_id, overview, content, text, created_at, visibility, url, repost_id, reply_id, + sensitive, ap_id, deleted, hide, move_to) +VALUES (1, 1, 0, null,'

test post

', 'hello', 1234455, 0, 'https://localhost/users/1/posts/1', null, null, false, + 'https://users/1/posts/1'); diff --git a/hideout-mastodon/src/test/resources/sql/test-user.sql b/hideout-mastodon/src/test/resources/sql/test-user.sql new file mode 100644 index 00000000..728af6f5 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/test-user.sql @@ -0,0 +1,11 @@ +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) +VALUES (1, 'test-user', 'example.com', 'Im test user.', 'THis account is test user.', + 'https://example.com/users/test-user/inbox', + 'https://example.com/users/test-user/outbox', 'https://example.com/users/test-user', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user#pubkey', 'https://example.com/users/test-user/following', + 'https://example.com/users/test-users/followers', 0, false, 0, 0, 0, null); + diff --git a/hideout-mastodon/src/test/resources/sql/test-user2.sql b/hideout-mastodon/src/test/resources/sql/test-user2.sql new file mode 100644 index 00000000..0f736704 --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/test-user2.sql @@ -0,0 +1,10 @@ +insert into "actors" (id, name, domain, screen_name, description, inbox, outbox, url, public_key, private_key, + created_at, key_id, following, followers, instance, locked, following_count, followers_count, + posts_count, last_post_at) +VALUES (2, 'test-user2', 'example.com', 'Im test user.', 'THis account is test user.', + 'https://example.com/users/test-user2/inbox', + 'https://example.com/users/test-user2/outbox', 'https://example.com/users/test-user2', + '-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----', + '-----BEGIN PRIVATE KEY-----...-----END PRIVATE KEY-----', 12345678, + 'https://example.com/users/test-user2#pubkey', 'https://example.com/users/test-user2/following', + 'https://example.com/users/test-user2s/followers', 0, false, 0, 0, 0, null); diff --git a/hideout-mastodon/src/test/resources/sql/userdetail.sql b/hideout-mastodon/src/test/resources/sql/userdetail.sql new file mode 100644 index 00000000..c0b3ee2d --- /dev/null +++ b/hideout-mastodon/src/test/resources/sql/userdetail.sql @@ -0,0 +1,2 @@ +insert into user_details(id, actor_id, password, auto_accept_followee_follow_request, last_migration, home_timeline_id) +VALUES (1, 1, 'veeeeeeeeeeryStrongPassword', false, null, null); \ No newline at end of file From 5cc82671357fb777f3d0ad81fd9ab4f05ed8e587 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 01:08:25 +0900 Subject: [PATCH 02/56] =?UTF-8?q?test:=20MediaAPI=E3=81=AE=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E5=BE=A9=E6=B4=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + .../mastodon/interfaces/api/SpringMediaApi.kt | 14 ++++++++++++++ .../src/test/kotlin/mastodon/media/MediaTest.kt | 2 +- .../src/test/resources/media/400x400.png | Bin 4 files changed, 16 insertions(+), 1 deletion(-) rename {hideout-core => hideout-mastodon}/src/test/resources/media/400x400.png (100%) diff --git a/.gitignore b/.gitignore index ecde199b..99c1c155 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,4 @@ out/ /http-client.private.env.json /logs/ /hideout-mastodon/logs/ +/hideout-mastodon/files/ diff --git a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringMediaApi.kt b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringMediaApi.kt index d5bed541..a28dafbb 100644 --- a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringMediaApi.kt +++ b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringMediaApi.kt @@ -21,9 +21,12 @@ import dev.usbharu.hideout.core.application.media.UploadMediaApplicationService import dev.usbharu.hideout.core.infrastructure.springframework.oauth2.SpringSecurityOauth2PrincipalContextHolder import dev.usbharu.hideout.mastodon.interfaces.api.generated.MediaApi import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.MediaAttachment +import org.slf4j.LoggerFactory +import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.stereotype.Controller import org.springframework.web.multipart.MultipartFile +import org.springframework.web.server.ResponseStatusException import java.nio.file.Files @Controller @@ -37,6 +40,13 @@ class SpringMediaApi( description: String?, focus: String?, ): ResponseEntity { + + if (file.size == 0L) { + logger.warn("File is empty.") + throw ResponseStatusException(HttpStatus.BAD_REQUEST, "File is empty.") + } + + val tempFile = Files.createTempFile("hideout-tmp-file", ".tmp") Files.newOutputStream(tempFile).use { outputStream -> @@ -73,4 +83,8 @@ class SpringMediaApi( ) ) } + + companion object { + private val logger = LoggerFactory.getLogger(SpringMediaApi::class.java) + } } diff --git a/hideout-mastodon/src/test/kotlin/mastodon/media/MediaTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/media/MediaTest.kt index 13d2bd55..7e4755d9 100644 --- a/hideout-mastodon/src/test/kotlin/mastodon/media/MediaTest.kt +++ b/hideout-mastodon/src/test/kotlin/mastodon/media/MediaTest.kt @@ -40,7 +40,7 @@ import org.springframework.web.context.WebApplicationContext @SpringBootTest(classes = [SpringApplication::class]) @AutoConfigureMockMvc @Transactional -@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +@Sql("/sql/actors.sql","/sql/userdetail.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) class MediaTest { @Autowired diff --git a/hideout-core/src/test/resources/media/400x400.png b/hideout-mastodon/src/test/resources/media/400x400.png similarity index 100% rename from hideout-core/src/test/resources/media/400x400.png rename to hideout-mastodon/src/test/resources/media/400x400.png From cb52248b1c24619c1a7e2cfb95374afa18dabb37 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 01:43:00 +0900 Subject: [PATCH 03/56] =?UTF-8?q?test:=20Filter=20API=E3=81=AE=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E4=B8=80=E9=83=A8=E5=BE=A9=E6=B4=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/PermissionDeniedException.kt | 3 +++ .../filter/UserGetFilterApplicationService.kt | 3 ++- .../DeleteFilterV1ApplicationService.kt | 2 +- .../filter/GetFilterV1ApplicationService.kt | 2 +- .../interfaces/api/SpringFilterApi.kt | 5 +++-- .../test/kotlin/mastodon/filter/FilterTest.kt | 19 ++++++++++--------- .../test/kotlin/mastodon/status/StatusTest.kt | 2 +- .../mastodon/timelines/TimelineApiTest.kt | 2 +- .../test/resources/sql/filter/test-filter.sql | 2 +- 9 files changed, 23 insertions(+), 17 deletions(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/exception/PermissionDeniedException.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/exception/PermissionDeniedException.kt index e59663be..53613621 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/exception/PermissionDeniedException.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/exception/PermissionDeniedException.kt @@ -16,7 +16,10 @@ package dev.usbharu.hideout.core.application.exception +import dev.usbharu.hideout.core.domain.model.support.principal.Principal + class PermissionDeniedException : RuntimeException { + constructor(principal: Principal) : super("Permission Denied $principal") constructor() : super() constructor(message: String?) : super(message) constructor(message: String?, cause: Throwable?) : super(message, cause) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/filter/UserGetFilterApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/filter/UserGetFilterApplicationService.kt index e97209fc..b6682c64 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/filter/UserGetFilterApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/filter/UserGetFilterApplicationService.kt @@ -34,7 +34,8 @@ class UserGetFilterApplicationService(private val filterRepository: FilterReposi ) { override suspend fun internalExecute(command: GetFilter, principal: LocalUser): Filter { val filter = - filterRepository.findByFilterId(FilterId(command.filterId)) ?: throw IllegalArgumentException("Not Found") + filterRepository.findByFilterId(FilterId(command.filterId)) + ?: throw IllegalArgumentException("Filter ${command.filterId} not found.") if (filter.userDetailId != principal.userDetailId) { throw PermissionDeniedException() } diff --git a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/application/filter/DeleteFilterV1ApplicationService.kt b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/application/filter/DeleteFilterV1ApplicationService.kt index 4961d383..53ed42ff 100644 --- a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/application/filter/DeleteFilterV1ApplicationService.kt +++ b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/application/filter/DeleteFilterV1ApplicationService.kt @@ -33,7 +33,7 @@ class DeleteFilterV1ApplicationService(private val filterRepository: FilterRepos ) { override suspend fun internalExecute(command: DeleteFilterV1, principal: LocalUser) { val filter = filterRepository.findByFilterKeywordId(FilterKeywordId(command.filterKeywordId)) - ?: throw IllegalArgumentException("Filter ${command.filterKeywordId} not found") + ?: throw IllegalArgumentException("Filter ${command.filterKeywordId} by KeywordId not found") if (principal.userDetailId != filter.userDetailId) { throw PermissionDeniedException() } diff --git a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/application/filter/GetFilterV1ApplicationService.kt b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/application/filter/GetFilterV1ApplicationService.kt index 6f485361..25e7f658 100644 --- a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/application/filter/GetFilterV1ApplicationService.kt +++ b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/application/filter/GetFilterV1ApplicationService.kt @@ -39,7 +39,7 @@ class GetFilterV1ApplicationService(private val filterRepository: FilterReposito ?: throw IllegalArgumentException("Filter ${command.filterKeywordId} not found") if (filter.userDetailId != principal.userDetailId) { - throw PermissionDeniedException() + throw PermissionDeniedException(principal) } val filterKeyword = filter.filterKeywords.find { it.id.id == command.filterKeywordId } diff --git a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringFilterApi.kt b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringFilterApi.kt index 1734be87..8e92209e 100644 --- a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringFilterApi.kt +++ b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringFilterApi.kt @@ -84,6 +84,7 @@ class SpringFilterApi( account -> FilterContext.ACCOUNT } }.toSet() + val principal = principalContextHolder.getPrincipal() val filter = userRegisterFilterApplicationService.execute( RegisterFilter( v1FilterPostRequest.phrase, @@ -91,12 +92,12 @@ class SpringFilterApi( FilterAction.WARN, setOf(RegisterFilterKeyword(v1FilterPostRequest.phrase, filterMode)) ), - principalContextHolder.getPrincipal() + principal ) return ResponseEntity.ok( getFilterV1ApplicationService.execute( GetFilterV1(filter.filterKeywords.first().id), - principalContextHolder.getPrincipal() + principal ) ) } diff --git a/hideout-mastodon/src/test/kotlin/mastodon/filter/FilterTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/filter/FilterTest.kt index 73615a07..8052c258 100644 --- a/hideout-mastodon/src/test/kotlin/mastodon/filter/FilterTest.kt +++ b/hideout-mastodon/src/test/kotlin/mastodon/filter/FilterTest.kt @@ -418,7 +418,7 @@ class FilterTest { ) } .asyncDispatch() - .andExpect { status { isOk() } } + .andExpect { status { isNotFound() } } } @Test @@ -431,7 +431,7 @@ class FilterTest { ) } .asyncDispatch() - .andExpect { status { isOk() } } + .andExpect { status { isNotFound() } } } @Test @@ -456,7 +456,7 @@ class FilterTest { ) } .asyncDispatch() - .andExpect { status { isOk() } } + .andExpect { status { isNotFound() } } } @Test @@ -469,7 +469,7 @@ class FilterTest { ) } .asyncDispatch() - .andExpect { status { isOk() } } + .andExpect { status { isNotFound() } } } @Test @@ -494,7 +494,7 @@ class FilterTest { ) } .asyncDispatch() - .andExpect { status { isOk() } } + .andExpect { status { isNotFound() } } } @Test @@ -507,7 +507,7 @@ class FilterTest { ) } .asyncDispatch() - .andExpect { status { isOk() } } + .andExpect { status { isNotFound() } } } @Test @@ -664,6 +664,7 @@ class FilterTest { } @Test + @Sql("/sql/filter/test-filter.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) fun `apiV1FiltersIdDelete writeで削除できる`() { mockMvc .delete("/api/v1/filters/1") { @@ -676,6 +677,7 @@ class FilterTest { } @Test + @Sql("/sql/filter/test-filter.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) fun `apiV1FiltersIdDelete write_filtersで削除できる`() { mockMvc .delete("/api/v1/filters/1") { @@ -692,11 +694,10 @@ class FilterTest { mockMvc .delete("/api/v1/filters/1") { with( - jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_write")) + jwt().jwt { it.claim("uid", "1") }.authorities(SimpleGrantedAuthority("SCOPE_read")) ) } - .asyncDispatch() - .andExpect { status { isOk() } } + .andExpect { status { isForbidden() } } } companion object { diff --git a/hideout-mastodon/src/test/kotlin/mastodon/status/StatusTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/status/StatusTest.kt index 790c3cc6..35a4a8a6 100644 --- a/hideout-mastodon/src/test/kotlin/mastodon/status/StatusTest.kt +++ b/hideout-mastodon/src/test/kotlin/mastodon/status/StatusTest.kt @@ -49,7 +49,7 @@ import org.springframework.web.context.WebApplicationContext @SpringBootTest(classes = [SpringApplication::class]) @AutoConfigureMockMvc @Transactional -@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +@Sql("/sql/actors.sql", "/sql/userdetail.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) @Sql("/sql/posts.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) @Sql("/sql/test-custom-emoji.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) class StatusTest { diff --git a/hideout-mastodon/src/test/kotlin/mastodon/timelines/TimelineApiTest.kt b/hideout-mastodon/src/test/kotlin/mastodon/timelines/TimelineApiTest.kt index 4d20bcfb..3f6bf40a 100644 --- a/hideout-mastodon/src/test/kotlin/mastodon/timelines/TimelineApiTest.kt +++ b/hideout-mastodon/src/test/kotlin/mastodon/timelines/TimelineApiTest.kt @@ -37,7 +37,7 @@ import org.springframework.web.context.WebApplicationContext @SpringBootTest(classes = [SpringApplication::class]) @Transactional -@Sql("/sql/actors.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) +@Sql("/sql/actors.sql", "/sql/userdetail.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS) class TimelineApiTest { @Autowired private lateinit var context: WebApplicationContext diff --git a/hideout-mastodon/src/test/resources/sql/filter/test-filter.sql b/hideout-mastodon/src/test/resources/sql/filter/test-filter.sql index d06d6bc0..8eab045a 100644 --- a/hideout-mastodon/src/test/resources/sql/filter/test-filter.sql +++ b/hideout-mastodon/src/test/resources/sql/filter/test-filter.sql @@ -1,4 +1,4 @@ insert into filters (id, user_id, name, context, action) -VALUES (1, 1, 'test filter', 'home', 'warn'); +VALUES (1, 1, 'test filter', 'HOME', 'WARN'); insert into filter_keywords(id, filter_id, keyword, mode) VALUES (1, 1, 'hoge', 'NONE') \ No newline at end of file From f83d47e8779e89748af92f61c66651c3305815fa Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 22:34:24 +0900 Subject: [PATCH 04/56] =?UTF-8?q?chore:=20CI=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout-core-pull-request-merge-check.yml | 163 ++++++++++++++++++ hideout-core/build.gradle.kts | 8 +- 2 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/hideout-core-pull-request-merge-check.yml diff --git a/.github/workflows/hideout-core-pull-request-merge-check.yml b/.github/workflows/hideout-core-pull-request-merge-check.yml new file mode 100644 index 00000000..ecdbd654 --- /dev/null +++ b/.github/workflows/hideout-core-pull-request-merge-check.yml @@ -0,0 +1,163 @@ +name: hideout-core-pull-request-merge-check.yml +on: + pull_request: + branches: + - "develop" + types: + - opened + - reopened + - synchronize + - ready_for_review + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + change: + if: github.event.pull_request.draft == false + runs-on: ubuntu-latest + outputs: + core: ${{ steps.filter.outputs.core }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Check Changes + uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + core: + - 'hideout-core/**' + - 'libs.versions.toml' + ap: + - 'hideout-activitypub/**' + - 'libs.versions.toml' + mastodon: + - 'hideout-mastodon/**' + - 'libs.versions.toml' + owl: + - 'owl/**' + - 'libs.versions.toml' + + hideout-core-setup: + needs: + - change + if: github.event.pull_request.draft == false && needs.change.outputs.core == true + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Gradle Wrapper Validation + uses: gradle/actions/wrapper-validation@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false + gradle-home-cache-cleanup: true + + - name: Build + run: ./gradlew classes --no-daemon + + hideout-core-unit-test: + needs: + - hideout-core-setup + - change + if: github.event.pull_request.draft == false && needs.change.outputs.core == true + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false + gradle-home-cache-cleanup: true + + - name: Unit Test + run: ./hideout-core/gradlew :hideout-core:koverXmlReport + + - name: JUnit Test Report + uses: mikepenz/action-junit-report@v4 + with: + report_paths: '**/TEST-*.xml' + check_name: 'hideout-core JUnit Test Report' + + - name: Upload Coverage Report + uses: actions/upload-artifact@v4 + with: + name: 'hideout-core.xml' + path: 'hideout-core/build/reports/kover/hideout-core.xml' + + coverage: + needs: + - change + - hideout-core-unit-test + runs-on: ubuntu-latest + steps: + - name: Download Coverage Report + uses: actions/download-artifact@v4 + with: + name: 'hideout-core.xml' + path: 'hideout-core/build/reports/kover/hideout-core.xml' + - name: Report Coverage + uses: madrapps/jacoco-report@v1.7.0 + with: + paths: | + ${{ github.workspace }}/hideout-core/build/reports/kover/**.xml + token: ${{ secrets.GITHUB_TOKEN }} + title: Code Coverage + update-comment: true + min-coverage-overall: 50 + min-coverage-changed-files: 80 + + lint: + needs: + - change + - hideout-core-setup + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + token: ${{ secrets.PAT }} + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false + gradle-home-cache-cleanup: true + + - name: Lint + run: ./gradlew :hideout-core:detektMain :hideout-mastodon:detektMain + + - name: Auto Commit + if: ${{ always() }} + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "style: fix lint (CI)" \ No newline at end of file diff --git a/hideout-core/build.gradle.kts b/hideout-core/build.gradle.kts index a9247b41..9be112b5 100644 --- a/hideout-core/build.gradle.kts +++ b/hideout-core/build.gradle.kts @@ -211,12 +211,17 @@ kover { reports { verify { rule { - bound{ + bound { minValue = 50 coverageUnits = CoverageUnit.INSTRUCTION } } } + total { + xml { + xmlFile = file("$buildDir/reports/kover/hideout-core.xml") + } + } filters { excludes { annotatedBy("org.springframework.context.annotation.Configuration") @@ -229,6 +234,7 @@ kover { packages("org.jetbrains") } } + } } From f7e151b575e718d7e351bfddff43d7f241aafa22 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 22:37:44 +0900 Subject: [PATCH 05/56] =?UTF-8?q?chore:=20CI=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/hideout-core-pull-request-merge-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/hideout-core-pull-request-merge-check.yml b/.github/workflows/hideout-core-pull-request-merge-check.yml index ecdbd654..9b58425a 100644 --- a/.github/workflows/hideout-core-pull-request-merge-check.yml +++ b/.github/workflows/hideout-core-pull-request-merge-check.yml @@ -46,7 +46,7 @@ jobs: hideout-core-setup: needs: - change - if: github.event.pull_request.draft == false && needs.change.outputs.core == true + if: github.event.pull_request.draft == false && needs.change.outputs.core == 'true' runs-on: ubuntu-latest steps: - name: Checkout @@ -76,7 +76,7 @@ jobs: needs: - hideout-core-setup - change - if: github.event.pull_request.draft == false && needs.change.outputs.core == true + if: github.event.pull_request.draft == false && needs.change.outputs.core == 'true' runs-on: ubuntu-latest steps: - name: Checkout From 572ceacc676edbb877e1781bd4908d13da5248ee Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 13:40:48 +0000 Subject: [PATCH 06/56] style: fix lint (CI) --- .../usbharu/hideout/mastodon/interfaces/api/SpringMediaApi.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringMediaApi.kt b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringMediaApi.kt index a28dafbb..3834f11e 100644 --- a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringMediaApi.kt +++ b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/interfaces/api/SpringMediaApi.kt @@ -40,13 +40,11 @@ class SpringMediaApi( description: String?, focus: String?, ): ResponseEntity { - if (file.size == 0L) { logger.warn("File is empty.") throw ResponseStatusException(HttpStatus.BAD_REQUEST, "File is empty.") } - val tempFile = Files.createTempFile("hideout-tmp-file", ".tmp") Files.newOutputStream(tempFile).use { outputStream -> From 26e06794356a82703d10bd68f285d867fff7bab4 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 22:43:47 +0900 Subject: [PATCH 07/56] =?UTF-8?q?chore:=20Java=E3=81=AE=E3=83=90=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=83=A7=E3=83=B3=E3=82=92=E6=8C=87=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/hideout-core-pull-request-merge-check.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/hideout-core-pull-request-merge-check.yml b/.github/workflows/hideout-core-pull-request-merge-check.yml index 9b58425a..921ab8d7 100644 --- a/.github/workflows/hideout-core-pull-request-merge-check.yml +++ b/.github/workflows/hideout-core-pull-request-merge-check.yml @@ -84,6 +84,12 @@ jobs: with: token: ${{ secrets.PAT }} + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: From a4cfbe81a1032c4dd74667f4c55caef5cfead707 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 22:51:46 +0900 Subject: [PATCH 08/56] =?UTF-8?q?chore:=20=E3=82=AB=E3=83=90=E3=83=AC?= =?UTF-8?q?=E3=83=83=E3=82=B8=E3=83=AC=E3=83=9D=E3=83=BC=E3=83=88=E3=81=AE?= =?UTF-8?q?=E9=9B=86=E8=A8=88=E5=A0=B4=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hideout-core-pull-request-merge-check.yml | 169 ------------------ .../workflows/pull-request-merge-check.yml | 108 +++++++---- 2 files changed, 73 insertions(+), 204 deletions(-) delete mode 100644 .github/workflows/hideout-core-pull-request-merge-check.yml diff --git a/.github/workflows/hideout-core-pull-request-merge-check.yml b/.github/workflows/hideout-core-pull-request-merge-check.yml deleted file mode 100644 index 921ab8d7..00000000 --- a/.github/workflows/hideout-core-pull-request-merge-check.yml +++ /dev/null @@ -1,169 +0,0 @@ -name: hideout-core-pull-request-merge-check.yml -on: - pull_request: - branches: - - "develop" - types: - - opened - - reopened - - synchronize - - ready_for_review - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true - -jobs: - change: - if: github.event.pull_request.draft == false - runs-on: ubuntu-latest - outputs: - core: ${{ steps.filter.outputs.core }} - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - token: ${{ secrets.PAT }} - - - name: Check Changes - uses: dorny/paths-filter@v2 - id: filter - with: - filters: | - core: - - 'hideout-core/**' - - 'libs.versions.toml' - ap: - - 'hideout-activitypub/**' - - 'libs.versions.toml' - mastodon: - - 'hideout-mastodon/**' - - 'libs.versions.toml' - owl: - - 'owl/**' - - 'libs.versions.toml' - - hideout-core-setup: - needs: - - change - if: github.event.pull_request.draft == false && needs.change.outputs.core == 'true' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - token: ${{ secrets.PAT }} - - - name: Gradle Wrapper Validation - uses: gradle/actions/wrapper-validation@v4 - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - cache-read-only: false - gradle-home-cache-cleanup: true - - - name: Build - run: ./gradlew classes --no-daemon - - hideout-core-unit-test: - needs: - - hideout-core-setup - - change - if: github.event.pull_request.draft == false && needs.change.outputs.core == 'true' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - token: ${{ secrets.PAT }} - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - cache-read-only: false - gradle-home-cache-cleanup: true - - - name: Unit Test - run: ./hideout-core/gradlew :hideout-core:koverXmlReport - - - name: JUnit Test Report - uses: mikepenz/action-junit-report@v4 - with: - report_paths: '**/TEST-*.xml' - check_name: 'hideout-core JUnit Test Report' - - - name: Upload Coverage Report - uses: actions/upload-artifact@v4 - with: - name: 'hideout-core.xml' - path: 'hideout-core/build/reports/kover/hideout-core.xml' - - coverage: - needs: - - change - - hideout-core-unit-test - runs-on: ubuntu-latest - steps: - - name: Download Coverage Report - uses: actions/download-artifact@v4 - with: - name: 'hideout-core.xml' - path: 'hideout-core/build/reports/kover/hideout-core.xml' - - name: Report Coverage - uses: madrapps/jacoco-report@v1.7.0 - with: - paths: | - ${{ github.workspace }}/hideout-core/build/reports/kover/**.xml - token: ${{ secrets.GITHUB_TOKEN }} - title: Code Coverage - update-comment: true - min-coverage-overall: 50 - min-coverage-changed-files: 80 - - lint: - needs: - - change - - hideout-core-setup - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - ref: ${{ github.head_ref }} - token: ${{ secrets.PAT }} - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - cache-read-only: false - gradle-home-cache-cleanup: true - - - name: Lint - run: ./gradlew :hideout-core:detektMain :hideout-mastodon:detektMain - - - name: Auto Commit - if: ${{ always() }} - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: "style: fix lint (CI)" \ No newline at end of file diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index c100e253..b3ecb96e 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -1,31 +1,53 @@ -name: PullRequest Merge Check - +name: pull-request-merge-check.yml on: pull_request: - paths-ignore: - - 'owl/**' branches: - "develop" types: - - opened # default - - reopened # default - - synchronize # default - - ready_for_review # 必要 + - opened + - reopened + - synchronize + - ready_for_review + concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true -permissions: - contents: read - checks: write - id-token: write - pull-requests: write - jobs: - setup: - name: Setup + change: if: github.event.pull_request.draft == false runs-on: ubuntu-latest + outputs: + core: ${{ steps.filter.outputs.core }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Check Changes + uses: dorny/paths-filter@v2 + id: filter + with: + filters: | + core: + - 'hideout-core/**' + - 'libs.versions.toml' + ap: + - 'hideout-activitypub/**' + - 'libs.versions.toml' + mastodon: + - 'hideout-mastodon/**' + - 'libs.versions.toml' + owl: + - 'owl/**' + - 'libs.versions.toml' + + hideout-core-setup: + needs: + - change + if: github.event.pull_request.draft == false && needs.change.outputs.core == 'true' + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 @@ -50,9 +72,11 @@ jobs: - name: Build run: ./gradlew classes --no-daemon - unit-test: - name: Unit Test - needs: [ setup ] + hideout-core-unit-test: + needs: + - hideout-core-setup + - change + if: github.event.pull_request.draft == false && needs.change.outputs.core == 'true' runs-on: ubuntu-latest steps: - name: Checkout @@ -75,30 +99,44 @@ jobs: - name: Unit Test run: ./hideout-core/gradlew :hideout-core:koverXmlReport - - name: Add coverage report to PR - if: always() - id: kover + - name: JUnit Test Report + uses: mikepenz/action-junit-report@v4 + with: + report_paths: '**/TEST-*.xml' + check_name: 'hideout-core JUnit Test Report' + + - name: Upload Coverage Report + uses: actions/upload-artifact@v4 + with: + name: 'hideout-core.xml' + path: 'hideout-core/build/reports/kover/hideout-core.xml' + + coverage: + needs: + - change + - hideout-core-unit-test + runs-on: ubuntu-latest + steps: + - name: Download Coverage Report + uses: actions/download-artifact@v4 + with: + name: 'hideout-core.xml' + path: 'hideout-core/build/reports/kover/hideout-core.xml' + - name: Report Coverage uses: madrapps/jacoco-report@v1.7.0 with: paths: | - ${{ github.workspace }}/hideout-core/build/reports/kover/report.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml token: ${{ secrets.GITHUB_TOKEN }} title: Code Coverage update-comment: true min-coverage-overall: 50 min-coverage-changed-files: 80 - - name: JUnit Test Report - uses: mikepenz/action-junit-report@v4 - with: - report_paths: '**/TEST-*.xml' - - - name: Verify Coverage - run: ./hideout-core/gradlew :hideout-core:koverVerify - lint: - name: Lint - needs: [ setup ] + needs: + - change + - hideout-core-setup runs-on: ubuntu-latest permissions: contents: write @@ -107,7 +145,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} - token: '${{ secrets.PAT }}' + token: ${{ secrets.PAT }} - name: Set up JDK 21 uses: actions/setup-java@v4 @@ -121,7 +159,7 @@ jobs: cache-read-only: false gradle-home-cache-cleanup: true - - name: Build with Gradle + - name: Lint run: ./gradlew :hideout-core:detektMain :hideout-mastodon:detektMain - name: Auto Commit From bd74ca1e0fc09d0997e2a4bd756db3f4b9558b01 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 23:02:18 +0900 Subject: [PATCH 09/56] =?UTF-8?q?chore:=20=E3=82=AB=E3=83=90=E3=83=AC?= =?UTF-8?q?=E3=83=83=E3=82=B8=E3=83=AC=E3=83=9D=E3=83=BC=E3=83=88=E3=81=AE?= =?UTF-8?q?=E9=9B=86=E8=A8=88=E5=A0=B4=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index b3ecb96e..27190b24 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -122,6 +122,7 @@ jobs: with: name: 'hideout-core.xml' path: 'hideout-core/build/reports/kover/hideout-core.xml' + - run: echo ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml - name: Report Coverage uses: madrapps/jacoco-report@v1.7.0 with: From e6573ccbb31e4540e58e1f6a740d45e4295043c4 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 23:12:50 +0900 Subject: [PATCH 10/56] =?UTF-8?q?chore:=20=E3=82=AB=E3=83=90=E3=83=AC?= =?UTF-8?q?=E3=83=83=E3=82=B8=E3=83=AC=E3=83=9D=E3=83=BC=E3=83=88=E3=81=AE?= =?UTF-8?q?=E9=9B=86=E8=A8=88=E5=A0=B4=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 27190b24..c834735e 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -121,8 +121,7 @@ jobs: uses: actions/download-artifact@v4 with: name: 'hideout-core.xml' - path: 'hideout-core/build/reports/kover/hideout-core.xml' - - run: echo ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml + path: 'hideout-core/build/reports/kover/' - name: Report Coverage uses: madrapps/jacoco-report@v1.7.0 with: From 375113f384e40470a64b1176446af461d2b80b06 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 23:17:56 +0900 Subject: [PATCH 11/56] =?UTF-8?q?chore:=20=E6=A8=A9=E9=99=90=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index c834735e..f751ea1c 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -13,6 +13,12 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +permissions: + contents: read + checks: write + id-token: write + pull-requests: write + jobs: change: if: github.event.pull_request.draft == false From 5456413e42c5c5aa6d02ef23e4fd208c58949f67 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 23:39:12 +0900 Subject: [PATCH 12/56] =?UTF-8?q?chore:=20mastodon=E3=81=A7=E3=82=82?= =?UTF-8?q?=E3=82=AB=E3=83=90=E3=83=AC=E3=83=83=E3=82=B8=E7=8E=87=E3=82=92?= =?UTF-8?q?=E8=A8=88=E6=B8=AC=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workflows/pull-request-merge-check.yml | 76 ++++++++++++++++++- hideout-mastodon/build.gradle.kts | 48 ++++++++++++ 2 files changed, 121 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index f751ea1c..701df932 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -76,7 +76,36 @@ jobs: gradle-home-cache-cleanup: true - name: Build - run: ./gradlew classes --no-daemon + run: ./gradlew :hideout-core:classes --no-daemon + + hideout-mastodon-setup: + needs: + - change + if: github.event.pull_request.draft == false && needs.change.outputs.mastodon == 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Gradle Wrapper Validation + uses: gradle/actions/wrapper-validation@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false + gradle-home-cache-cleanup: true + + - name: Build + run: ./gradlew :hideout-mastodon:classes --no-daemon hideout-core-unit-test: needs: @@ -117,22 +146,62 @@ jobs: name: 'hideout-core.xml' path: 'hideout-core/build/reports/kover/hideout-core.xml' + + hideout-mastodon-unit-test: + needs: + - hideout-mastodon-setup + - change + if: github.event.pull_request.draft == false && needs.change.outputs.mastodon == 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false + gradle-home-cache-cleanup: true + + - name: Unit Test + run: ./hideout-mastodon/gradlew :hideout-mastodon:koverXmlReport + + - name: JUnit Test Report + uses: mikepenz/action-junit-report@v4 + with: + report_paths: '**/TEST-*.xml' + check_name: 'hideout-core JUnit Test Report' + + - name: Upload Coverage Report + uses: actions/upload-artifact@v4 + with: + name: 'hideout-core.xml' + path: 'hideout-core/build/reports/kover/hideout-mastodon.xml' + coverage: needs: - change - hideout-core-unit-test + - hideout-mastodon-unit-test runs-on: ubuntu-latest steps: - name: Download Coverage Report uses: actions/download-artifact@v4 with: - name: 'hideout-core.xml' path: 'hideout-core/build/reports/kover/' - name: Report Coverage uses: madrapps/jacoco-report@v1.7.0 with: paths: | - ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/**.xml token: ${{ secrets.GITHUB_TOKEN }} title: Code Coverage update-comment: true @@ -143,6 +212,7 @@ jobs: needs: - change - hideout-core-setup + - hideout-mastodon-setup runs-on: ubuntu-latest permissions: contents: write diff --git a/hideout-mastodon/build.gradle.kts b/hideout-mastodon/build.gradle.kts index 12ad6ee8..38cd2c58 100644 --- a/hideout-mastodon/build.gradle.kts +++ b/hideout-mastodon/build.gradle.kts @@ -1,3 +1,4 @@ +import kotlinx.kover.gradle.plugin.dsl.CoverageUnit import org.openapitools.generator.gradle.plugin.tasks.GenerateTask plugins { @@ -6,6 +7,7 @@ plugins { alias(libs.plugins.spring.boot) alias(libs.plugins.kotlin.spring) alias(libs.plugins.detekt) + alias(libs.plugins.kover) } @@ -131,6 +133,52 @@ configurations.matching { it.name == "detekt" }.all { } } +project.gradle.taskGraph.whenReady { + if (this.hasTask(":koverGenerateArtifact")) { + val task = this.allTasks.find { it.name == "test" } + val verificationTask = task as VerificationTask + verificationTask.ignoreFailures = true + } +} + +kover { + currentProject { + sources { + + + } + } + + reports { + verify { + rule { + bound { + minValue = 50 + coverageUnits = CoverageUnit.INSTRUCTION + } + } + } + total { + xml { + xmlFile = file("$buildDir/reports/kover/hideout-core.xml") + } + } + filters { + excludes { + annotatedBy("org.springframework.context.annotation.Configuration") + annotatedBy("org.springframework.boot.context.properties.ConfigurationProperties") + packages( + "dev.usbharu.hideout.controller.mastodon.generated", + "dev.usbharu.hideout.domain.mastodon.model.generated" + ) + packages("org.springframework") + packages("org.jetbrains") + } + } + + } +} + tasks.withType { exclude("**/generated/**") doFirst { From af70c18b7ae687afd2c10920d9d3a33f9e0c793d Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 23:42:34 +0900 Subject: [PATCH 13/56] =?UTF-8?q?chore:=20output=E3=81=AE=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A=E3=82=92=E9=96=93=E9=81=95=E3=81=88=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=81=9F=E3=81=AE=E3=81=A7=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 701df932..1c1f54da 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -25,6 +25,7 @@ jobs: runs-on: ubuntu-latest outputs: core: ${{ steps.filter.outputs.core }} + mastodon: ${{ steps.filter.outputs.mastodon }} steps: - name: Checkout uses: actions/checkout@v4 From 6ffd675f35f2752fa394bbfb6d2908ee532b5ef0 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 23:46:39 +0900 Subject: [PATCH 14/56] =?UTF-8?q?chore:=20gradlew=E3=81=AE=E3=83=91?= =?UTF-8?q?=E3=83=BC=E3=83=9F=E3=83=83=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92?= =?UTF-8?q?=E8=A8=AD=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hideout-mastodon/gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 hideout-mastodon/gradlew diff --git a/hideout-mastodon/gradlew b/hideout-mastodon/gradlew old mode 100644 new mode 100755 From ee665eddb3927b2d797dae0fe8e58be173d1be36 Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 16 Sep 2024 23:56:38 +0900 Subject: [PATCH 15/56] =?UTF-8?q?chore:=20=E3=82=A2=E3=83=83=E3=83=97?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E3=83=89=E5=90=8D=E3=82=92=E9=96=93=E9=81=95?= =?UTF-8?q?=E3=81=88=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE=E3=81=A7=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 1c1f54da..d56e6e29 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -179,12 +179,12 @@ jobs: uses: mikepenz/action-junit-report@v4 with: report_paths: '**/TEST-*.xml' - check_name: 'hideout-core JUnit Test Report' + check_name: 'hideout-mastodon JUnit Test Report' - name: Upload Coverage Report uses: actions/upload-artifact@v4 with: - name: 'hideout-core.xml' + name: 'hideout-mastodon.xml' path: 'hideout-core/build/reports/kover/hideout-mastodon.xml' coverage: From e36c7d6fb945ba537884d5919d5d03d22187bb28 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 00:04:14 +0900 Subject: [PATCH 16/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 3 ++- hideout-mastodon/build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index d56e6e29..c83c9a5a 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -202,7 +202,8 @@ jobs: uses: madrapps/jacoco-report@v1.7.0 with: paths: | - ${{ github.workspace }}/hideout-core/build/reports/kover/**.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon.xml token: ${{ secrets.GITHUB_TOKEN }} title: Code Coverage update-comment: true diff --git a/hideout-mastodon/build.gradle.kts b/hideout-mastodon/build.gradle.kts index 38cd2c58..593eac69 100644 --- a/hideout-mastodon/build.gradle.kts +++ b/hideout-mastodon/build.gradle.kts @@ -160,7 +160,7 @@ kover { } total { xml { - xmlFile = file("$buildDir/reports/kover/hideout-core.xml") + xmlFile = file("$buildDir/reports/kover/hideout-mastodon.xml") } } filters { From 95ac60bfec3f6a4e91834baacf35d2a1d50b9e06 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 00:12:37 +0900 Subject: [PATCH 17/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index c83c9a5a..860df1ff 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -185,7 +185,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: 'hideout-mastodon.xml' - path: 'hideout-core/build/reports/kover/hideout-mastodon.xml' + path: 'hideout-mastodon/build/reports/kover/hideout-mastodon.xml' coverage: needs: From 031ba79450fb07ba4c4d976b2f9596e0a42f72b6 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 00:16:52 +0900 Subject: [PATCH 18/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 860df1ff..1be1b0ce 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -202,7 +202,7 @@ jobs: uses: madrapps/jacoco-report@v1.7.0 with: paths: | - ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml, ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon.xml token: ${{ secrets.GITHUB_TOKEN }} title: Code Coverage From 4eb81271051e93f13b1de76888b88e39faaecef0 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 00:26:33 +0900 Subject: [PATCH 19/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 1be1b0ce..31b9c75e 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -181,6 +181,8 @@ jobs: report_paths: '**/TEST-*.xml' check_name: 'hideout-mastodon JUnit Test Report' + - run: cd ./hideout-core/build/reports/kover || ls -lah + - name: Upload Coverage Report uses: actions/upload-artifact@v4 with: From 579ac443722fe27eb8fcb6b86edc4acdf99104d0 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 00:33:36 +0900 Subject: [PATCH 20/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 31b9c75e..3bf9ab15 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -181,8 +181,6 @@ jobs: report_paths: '**/TEST-*.xml' check_name: 'hideout-mastodon JUnit Test Report' - - run: cd ./hideout-core/build/reports/kover || ls -lah - - name: Upload Coverage Report uses: actions/upload-artifact@v4 with: @@ -200,6 +198,10 @@ jobs: uses: actions/download-artifact@v4 with: path: 'hideout-core/build/reports/kover/' + + + - run: cd ./hideout-core/build/reports/kover || ls -lah + - name: Report Coverage uses: madrapps/jacoco-report@v1.7.0 with: From bb6e03461ad9a1331ae5cd844ec124435a8e1e30 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 00:49:27 +0900 Subject: [PATCH 21/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 3bf9ab15..96134aad 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -197,10 +197,10 @@ jobs: - name: Download Coverage Report uses: actions/download-artifact@v4 with: - path: 'hideout-core/build/reports/kover/' + path: 'hideout-core/build/reports/kover' - - run: cd ./hideout-core/build/reports/kover || ls -lah + - run: ls -R hideout-core/build/reports/kover - name: Report Coverage uses: madrapps/jacoco-report@v1.7.0 From 23fb7f9f2a7c954d1170e3249360a65ef741090b Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 01:16:07 +0900 Subject: [PATCH 22/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 96134aad..28ad9803 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -206,8 +206,7 @@ jobs: uses: madrapps/jacoco-report@v1.7.0 with: paths: | - ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml, - ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/**/**.xml token: ${{ secrets.GITHUB_TOKEN }} title: Code Coverage update-comment: true From f622d23a7b000cf3fc4202e431d657d4bde0e9c2 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 01:24:04 +0900 Subject: [PATCH 23/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 28ad9803..477995c6 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -206,7 +206,8 @@ jobs: uses: madrapps/jacoco-report@v1.7.0 with: paths: | - ${{ github.workspace }}/hideout-core/build/reports/kover/**/**.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core/hideout-core.xml, + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon/hideout-mastodon.xml token: ${{ secrets.GITHUB_TOKEN }} title: Code Coverage update-comment: true From 4a9b192e84ebd8c8f37a298681e17c1484c98d7d Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 01:32:46 +0900 Subject: [PATCH 24/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 477995c6..e01b1658 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -202,6 +202,9 @@ jobs: - run: ls -R hideout-core/build/reports/kover + - run: cat ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core/hideout-core.xml + - run: cat ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon/hideout-mastodon.xml + - name: Report Coverage uses: madrapps/jacoco-report@v1.7.0 with: From 455c7aea3fed47079bbc91ef589c8891eb932d59 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 01:37:19 +0900 Subject: [PATCH 25/56] =?UTF-8?q?chore:=E3=80=80=E3=83=95=E3=82=A1?= =?UTF-8?q?=E3=82=A4=E3=83=AB=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index e01b1658..f9860945 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -202,15 +202,15 @@ jobs: - run: ls -R hideout-core/build/reports/kover - - run: cat ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core/hideout-core.xml - - run: cat ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon/hideout-mastodon.xml + - run: cat ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml/hideout-core.xml + - run: cat ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon.xml/hideout-mastodon.xml - name: Report Coverage uses: madrapps/jacoco-report@v1.7.0 with: paths: | - ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core/hideout-core.xml, - ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon/hideout-mastodon.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml/hideout-core.xml, + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon.xml/hideout-mastodon.xml token: ${{ secrets.GITHUB_TOKEN }} title: Code Coverage update-comment: true From ee7bdf66eb358689ca909848548432a977174328 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 01:47:34 +0900 Subject: [PATCH 26/56] =?UTF-8?q?chore:=E3=80=80=E3=82=AB=E3=83=90?= =?UTF-8?q?=E3=83=AC=E3=83=83=E3=82=B8=E3=83=AC=E3=83=9D=E3=83=BC=E3=83=88?= =?UTF-8?q?=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hideout-core/build.gradle.kts | 1 + hideout-mastodon/build.gradle.kts | 1 + 2 files changed, 2 insertions(+) diff --git a/hideout-core/build.gradle.kts b/hideout-core/build.gradle.kts index 9be112b5..b488437b 100644 --- a/hideout-core/build.gradle.kts +++ b/hideout-core/build.gradle.kts @@ -219,6 +219,7 @@ kover { } total { xml { + title = "Hideout Core" xmlFile = file("$buildDir/reports/kover/hideout-core.xml") } } diff --git a/hideout-mastodon/build.gradle.kts b/hideout-mastodon/build.gradle.kts index 593eac69..37094786 100644 --- a/hideout-mastodon/build.gradle.kts +++ b/hideout-mastodon/build.gradle.kts @@ -160,6 +160,7 @@ kover { } total { xml { + title = "Hideout Mastodon" xmlFile = file("$buildDir/reports/kover/hideout-mastodon.xml") } } From 3890659a7d277763be6e36e630a6fbdb207d939a Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 13:10:14 +0900 Subject: [PATCH 27/56] =?UTF-8?q?chore:=E3=80=80=E4=B8=8D=E8=A6=81?= =?UTF-8?q?=E3=81=AA=E3=82=B9=E3=83=86=E3=83=83=E3=83=97=E3=82=92=E5=89=8A?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index f9860945..7326f383 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -199,12 +199,6 @@ jobs: with: path: 'hideout-core/build/reports/kover' - - - run: ls -R hideout-core/build/reports/kover - - - run: cat ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml/hideout-core.xml - - run: cat ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon.xml/hideout-mastodon.xml - - name: Report Coverage uses: madrapps/jacoco-report@v1.7.0 with: From 3faf6b9c34b1f41b5481c96377ba4941b3323b0e Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 13:56:24 +0900 Subject: [PATCH 28/56] =?UTF-8?q?chore:=E3=80=80owl=E3=81=A8activitypub?= =?UTF-8?q?=E3=81=AB=E3=82=82lint=E3=81=A8=E3=82=B3=E3=83=BC=E3=83=89?= =?UTF-8?q?=E3=82=AB=E3=83=90=E3=83=AC=E3=83=83=E3=82=B8=E3=81=AE=E8=A8=88?= =?UTF-8?q?=E6=B8=AC=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../workflows/pull-request-merge-check.yml | 151 +++++++++++++++++- 1 file changed, 149 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 7326f383..1fa54bf5 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -26,6 +26,8 @@ jobs: outputs: core: ${{ steps.filter.outputs.core }} mastodon: ${{ steps.filter.outputs.mastodon }} + activitypub: ${{ steps.filter.outputs.ap }} + owl: $${{ steps.filter.outputs.owl }} steps: - name: Checkout uses: actions/checkout@v4 @@ -108,6 +110,64 @@ jobs: - name: Build run: ./gradlew :hideout-mastodon:classes --no-daemon + hideout-activitypub-setup: + needs: + - change + if: github.event.pull_request.draft == false && needs.change.outputs.activitypub == 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Gradle Wrapper Validation + uses: gradle/actions/wrapper-validation@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false + gradle-home-cache-cleanup: true + + - name: Build + run: ./gradlew :hideout-activitypub:classes --no-daemon + + owl-setup: + needs: + - change + if: github.event.pull_request.draft == false && needs.change.outputs.owl == 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Gradle Wrapper Validation + uses: gradle/actions/wrapper-validation@v4 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false + gradle-home-cache-cleanup: true + + - name: Build + run: ./owl/gradlew :owl:classes --no-daemon + hideout-core-unit-test: needs: - hideout-core-setup @@ -187,11 +247,90 @@ jobs: name: 'hideout-mastodon.xml' path: 'hideout-mastodon/build/reports/kover/hideout-mastodon.xml' + hideout-activitypub-unit-test: + needs: + - hideout-activitypub-setup + - change + if: github.event.pull_request.draft == false && needs.change.outputs.activitypub == 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false + gradle-home-cache-cleanup: true + + - name: Unit Test + run: ./hideout-activitypub/gradlew :hideout-activitypub:koverXmlReport + + - name: JUnit Test Report + uses: mikepenz/action-junit-report@v4 + with: + report_paths: '**/TEST-*.xml' + check_name: 'hideout-activitypub JUnit Test Report' + + - name: Upload Coverage Report + uses: actions/upload-artifact@v4 + with: + name: 'hideout-activitypub.xml' + path: 'hideout-activitypub/build/reports/kover/hideout-activitypub.xml' + + owl-unit-test: + needs: + - owl-setup + - change + if: github.event.pull_request.draft == false && needs.change.outputs.owl == 'true' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.PAT }} + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-read-only: false + gradle-home-cache-cleanup: true + + - name: Unit Test + run: ./owl/gradlew :owl:koverXmlReport + + - name: JUnit Test Report + uses: mikepenz/action-junit-report@v4 + with: + report_paths: '**/TEST-*.xml' + check_name: 'owl JUnit Test Report' + + - name: Upload Coverage Report + uses: actions/upload-artifact@v4 + with: + name: 'owl.xml' + path: 'owl/build/reports/kover/owl.xml' + coverage: needs: - change - hideout-core-unit-test - hideout-mastodon-unit-test + - hideout-activitypub-unit-test runs-on: ubuntu-latest steps: - name: Download Coverage Report @@ -204,7 +343,9 @@ jobs: with: paths: | ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml/hideout-core.xml, - ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon.xml/hideout-mastodon.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-mastodon.xml/hideout-mastodon.xml, + ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-activitypub.xml/hideout-activitypub.xml + ${{ github.workspace }}/hideout-core/build/reports/kover/owl.xml/owl.xml token: ${{ secrets.GITHUB_TOKEN }} title: Code Coverage update-comment: true @@ -216,6 +357,8 @@ jobs: - change - hideout-core-setup - hideout-mastodon-setup + - hideout-activitypub-setup + - owl-setup runs-on: ubuntu-latest permissions: contents: write @@ -239,7 +382,11 @@ jobs: gradle-home-cache-cleanup: true - name: Lint - run: ./gradlew :hideout-core:detektMain :hideout-mastodon:detektMain + run: ./gradlew :hideout-core:detektMain :hideout-mastodon:detektMain :hideout-activitypub:detektMain + + - name: owl Lint + if: always() + run: ./owl/gradlew :owl:detektMain - name: Auto Commit if: ${{ always() }} From 80a8a5dceec46f04c2e24fc5ebaa1235d3803a4a Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 14:01:26 +0900 Subject: [PATCH 29/56] =?UTF-8?q?chore:=E3=80=80=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=96=E3=81=AE=E4=BE=9D=E5=AD=98=E9=96=A2=E4=BF=82=E3=81=A8?= =?UTF-8?q?=E5=AE=9F=E8=A1=8C=E6=9D=A1=E4=BB=B6=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 1fa54bf5..df219854 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -326,11 +326,13 @@ jobs: path: 'owl/build/reports/kover/owl.xml' coverage: + if: needs.change.outputs.core == 'true' || needs.change.outputs.activitypub == 'true' || needs.change.outputs.mastodon == 'true' || needs.change.outputs.owl == 'true' needs: - change - hideout-core-unit-test - hideout-mastodon-unit-test - hideout-activitypub-unit-test + - owl-unit-test runs-on: ubuntu-latest steps: - name: Download Coverage Report @@ -353,6 +355,7 @@ jobs: min-coverage-changed-files: 80 lint: + if: needs.change.outputs.core == 'true' || needs.change.outputs.activitypub == 'true' || needs.change.outputs.mastodon == 'true' || needs.change.outputs.owl == 'true' needs: - change - hideout-core-setup From acb9efdfef622e79288b56458603190e79e03bb3 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 14:07:21 +0900 Subject: [PATCH 30/56] =?UTF-8?q?chore:=E3=80=80=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=96=E3=81=AE=E5=AE=9F=E8=A1=8C=E6=9D=A1=E4=BB=B6=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index df219854..aa68bd97 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -326,7 +326,7 @@ jobs: path: 'owl/build/reports/kover/owl.xml' coverage: - if: needs.change.outputs.core == 'true' || needs.change.outputs.activitypub == 'true' || needs.change.outputs.mastodon == 'true' || needs.change.outputs.owl == 'true' + if: always() && (needs.change.outputs.core == 'true' || needs.change.outputs.activitypub == 'true' || needs.change.outputs.mastodon == 'true' || needs.change.outputs.owl == 'true') needs: - change - hideout-core-unit-test @@ -355,7 +355,7 @@ jobs: min-coverage-changed-files: 80 lint: - if: needs.change.outputs.core == 'true' || needs.change.outputs.activitypub == 'true' || needs.change.outputs.mastodon == 'true' || needs.change.outputs.owl == 'true' + if: always() && (needs.change.outputs.core == 'true' || needs.change.outputs.activitypub == 'true' || needs.change.outputs.mastodon == 'true' || needs.change.outputs.owl == 'true') needs: - change - hideout-core-setup From 26b3bdd721a0a25854c7a8837a70d9a712376abb Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 21:24:25 +0900 Subject: [PATCH 31/56] =?UTF-8?q?chore:=E3=80=80owl=E3=81=A7kover=E3=81=8C?= =?UTF-8?q?=E5=8B=95=E4=BD=9C=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 3 + hideout-activitypub/build.gradle.kts | 90 ++++++++++++++++++- hideout-activitypub/settings.gradle.kts | 11 +++ owl/build.gradle.kts | 68 +++++++++++++- owl/gradle/wrapper/gradle-wrapper.properties | 2 +- owl/owl-broker/build.gradle.kts | 2 +- .../mongodb/MongodbConsumerRepositoryTest.kt | 2 + .../owl/broker/external/GrpcExtension.kt | 2 +- .../interfaces/grpc/AssignmentTaskService.kt | 4 +- .../interfaces/grpc/DefinitionTaskService.kt | 6 +- .../broker/interfaces/grpc/ProducerService.kt | 4 +- .../interfaces/grpc/SubscribeTaskService.kt | 4 +- .../interfaces/grpc/TaskPublishService.kt | 8 +- .../interfaces/grpc/TaskResultService.kt | 4 +- .../grpc/TaskResultSubscribeService.kt | 2 +- owl/owl-broker/src/main/proto/consumer.proto | 2 +- .../src/main/proto/definition_task.proto | 2 +- owl/owl-broker/src/main/proto/producer.proto | 2 +- owl/owl-broker/src/main/proto/property.proto | 2 +- .../src/main/proto/publish_task.proto | 2 +- owl/owl-broker/src/main/proto/task.proto | 2 +- .../src/main/proto/task_result.proto | 2 +- .../src/main/proto/task_result_producer.proto | 2 +- owl/owl-broker/src/main/proto/uuid.proto | 2 +- owl/owl-consumer/build.gradle.kts | 2 +- .../dev/usbharu/owl/consumer/Consumer.kt | 4 +- .../owl/consumer/StandaloneConsumer.kt | 6 +- .../owl-producer-default/build.gradle.kts | 2 +- .../defaultimpl/DefaultOwlProducer.kt | 6 +- settings.gradle.kts | 1 + 30 files changed, 209 insertions(+), 42 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index a6acf140..52f8a2b7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +import dev.usbharu.hideout.core.infrastructure.exposedrepository.UserDetails.password + /* * Copyright (C) 2024 usbharu * @@ -52,6 +54,7 @@ repositories { dependencies { implementation("dev.usbharu:hideout-core:0.0.1") implementation("dev.usbharu:hideout-mastodon:1.0-SNAPSHOT") + implementation("dev.usbharu:hideout-activitypub:1.0-SNAPSHOT") } tasks.register("run") { diff --git a/hideout-activitypub/build.gradle.kts b/hideout-activitypub/build.gradle.kts index 36ec82b7..6a2d223a 100644 --- a/hideout-activitypub/build.gradle.kts +++ b/hideout-activitypub/build.gradle.kts @@ -1,5 +1,10 @@ +import dev.usbharu.hideout.core.infrastructure.exposedrepository.Instance.version +import kotlinx.kover.gradle.plugin.dsl.CoverageUnit + plugins { - kotlin("jvm") version "1.9.25" + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.detekt) + alias(libs.plugins.kover) } group = "dev.usbharu" @@ -18,4 +23,85 @@ tasks.test { } kotlin { jvmToolchain(21) -} \ No newline at end of file +} + + +configurations { + matching { it.name == "detekt" }.all { + resolutionStrategy.eachDependency { + if (requested.group == "org.jetbrains.kotlin") { + useVersion(io.gitlab.arturbosch.detekt.getSupportedKotlinVersion()) + } + } + } + all { + exclude("org.apache.logging.log4j", "log4j-slf4j2-impl") + } +} + +tasks { + withType { + exclude("**/generated/**") + setSource("src/main/kotlin") + exclude("build/") + configureEach { + exclude("**/org/koin/ksp/generated/**", "**/generated/**") + } + } + withType() { + configureEach { + exclude("**/org/koin/ksp/generated/**", "**/generated/**") + } + } + withType { + useJUnitPlatform() + } +} + + +project.gradle.taskGraph.whenReady { + if (this.hasTask(":koverGenerateArtifact")) { + val task = this.allTasks.find { it.name == "test" } + val verificationTask = task as VerificationTask + verificationTask.ignoreFailures = true + } +} + +kover { + currentProject { + sources { + + + } + } + + reports { + verify { + rule { + bound { + minValue = 50 + coverageUnits = CoverageUnit.INSTRUCTION + } + } + } + total { + xml { + title = "Hideout ActivityPub" + xmlFile = file("$buildDir/reports/kover/hideout-activitypub.xml") + } + } + filters { + excludes { + annotatedBy("org.springframework.context.annotation.Configuration") + annotatedBy("org.springframework.boot.context.properties.ConfigurationProperties") + packages( + "dev.usbharu.hideout.controller.mastodon.generated", + "dev.usbharu.hideout.domain.mastodon.model.generated" + ) + packages("org.springframework") + packages("org.jetbrains") + } + } + + } +} diff --git a/hideout-activitypub/settings.gradle.kts b/hideout-activitypub/settings.gradle.kts index 8f4bdd48..c083363f 100644 --- a/hideout-activitypub/settings.gradle.kts +++ b/hideout-activitypub/settings.gradle.kts @@ -3,3 +3,14 @@ plugins { } rootProject.name = "hideout-activitypub" +dependencyResolutionManagement { + repositories { + mavenCentral() + } + + versionCatalogs { + create("libs") { + from(files("../libs.versions.toml")) + } + } +} \ No newline at end of file diff --git a/owl/build.gradle.kts b/owl/build.gradle.kts index fddf3a79..066d8b10 100644 --- a/owl/build.gradle.kts +++ b/owl/build.gradle.kts @@ -1,6 +1,10 @@ +import kotlinx.kover.gradle.plugin.dsl.CoverageUnit + plugins { alias(libs.plugins.kotlin.jvm) id("maven-publish") + alias(libs.plugins.kover) + alias(libs.plugins.detekt) } @@ -27,6 +31,7 @@ subprojects { apply { plugin("org.jetbrains.kotlin.jvm") plugin("maven-publish") + plugin(rootProject.libs.plugins.kover.get().pluginId) } kotlin { jvmToolchain(21) @@ -38,7 +43,13 @@ subprojects { } - + project.gradle.taskGraph.whenReady { + if (this.hasTask(":koverGenerateArtifact")) { + val task = this.allTasks.find { println(it.name);it.name == "test" } + val verificationTask = task as VerificationTask + verificationTask.ignoreFailures = true + } + } tasks.test { useJUnitPlatform() } @@ -69,4 +80,57 @@ subprojects { } } } -} \ No newline at end of file +} + +dependencies { + kover(project(":owl-broker")) + kover(project(":owl-broker:owl-broker-mongodb")) + kover(project(":owl-common")) + kover(project(":owl-common:owl-common-serialize-jackson")) + kover(project(":owl-consumer")) + kover(project(":owl-producer")) + kover(project(":owl-producer:owl-producer-api")) + kover(project(":owl-producer:owl-producer-default")) + kover(project(":owl-producer:owl-producer-embedded")) +} + + + +project.gradle.taskGraph.whenReady { + if (this.hasTask(":koverGenerateArtifact")) { + val task = this.allTasks.find { it.name == "test" } + val verificationTask = task as VerificationTask + verificationTask.ignoreFailures = true + } +} + +kover { + currentProject { + sources { + excludedSourceSets.addAll("grpc", "grpckt") + } + } + reports { + verify { + rule { + bound { + minValue = 50 + coverageUnits = CoverageUnit.INSTRUCTION + } + } + } + total { + xml { + title = "Hideout Core" + xmlFile = file("$buildDir/reports/kover/hideout-core.xml") + } + filters { + excludes { + packages("dev.usbharu.owl.generated") + } + } + } + + + } +} diff --git a/owl/gradle/wrapper/gradle-wrapper.properties b/owl/gradle/wrapper/gradle-wrapper.properties index 0aaefbca..9355b415 100644 --- a/owl/gradle/wrapper/gradle-wrapper.properties +++ b/owl/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/owl/owl-broker/build.gradle.kts b/owl/owl-broker/build.gradle.kts index 8c055cfc..42b90f13 100644 --- a/owl/owl-broker/build.gradle.kts +++ b/owl/owl-broker/build.gradle.kts @@ -35,7 +35,7 @@ protobuf { artifact = libs.protoc.gen.grpc.java.get().toString() } create("grpckt") { - artifact = libs.protoc.gen.grpc.kotlin.get().toString() + "jdk8@jar" + artifact = libs.protoc.gen.grpc.kotlin.get().toString() + ":jdk8@jar" } } generateProtoTasks { diff --git a/owl/owl-broker/owl-broker-mongodb/src/test/kotlin/dev/usbharu/owl/broker/mongodb/MongodbConsumerRepositoryTest.kt b/owl/owl-broker/owl-broker-mongodb/src/test/kotlin/dev/usbharu/owl/broker/mongodb/MongodbConsumerRepositoryTest.kt index b71c5ea4..2bd00586 100644 --- a/owl/owl-broker/owl-broker-mongodb/src/test/kotlin/dev/usbharu/owl/broker/mongodb/MongodbConsumerRepositoryTest.kt +++ b/owl/owl-broker/owl-broker-mongodb/src/test/kotlin/dev/usbharu/owl/broker/mongodb/MongodbConsumerRepositoryTest.kt @@ -7,12 +7,14 @@ import dev.usbharu.owl.broker.domain.model.consumer.Consumer import kotlinx.coroutines.runBlocking import org.bson.UuidRepresentation import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import java.util.* class MongodbConsumerRepositoryTest { @Test + @Disabled fun name() { val clientSettings = diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/external/GrpcExtension.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/external/GrpcExtension.kt index 4271b55c..93159174 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/external/GrpcExtension.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/external/GrpcExtension.kt @@ -17,7 +17,7 @@ package dev.usbharu.owl.broker.external import com.google.protobuf.Timestamp -import dev.usbharu.owl.Uuid +import dev.usbharu.owl.generated.Uuid import java.time.Instant import java.util.* diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/AssignmentTaskService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/AssignmentTaskService.kt index f92faf17..e3f0752c 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/AssignmentTaskService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/AssignmentTaskService.kt @@ -17,13 +17,13 @@ package dev.usbharu.owl.broker.interfaces.grpc -import dev.usbharu.owl.AssignmentTaskServiceGrpcKt -import dev.usbharu.owl.Task import dev.usbharu.owl.broker.external.toTimestamp import dev.usbharu.owl.broker.external.toUUID import dev.usbharu.owl.broker.service.QueuedTaskAssigner import dev.usbharu.owl.common.property.PropertySerializeUtils import dev.usbharu.owl.common.property.PropertySerializerFactory +import dev.usbharu.owl.generated.AssignmentTaskServiceGrpcKt +import dev.usbharu.owl.generated.Task import io.grpc.Status import io.grpc.StatusException import kotlinx.coroutines.flow.Flow diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/DefinitionTaskService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/DefinitionTaskService.kt index d00d584a..59afb0d1 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/DefinitionTaskService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/DefinitionTaskService.kt @@ -17,11 +17,11 @@ package dev.usbharu.owl.broker.interfaces.grpc import com.google.protobuf.Empty -import dev.usbharu.owl.DefinitionTask -import dev.usbharu.owl.DefinitionTask.TaskDefined -import dev.usbharu.owl.DefinitionTaskServiceGrpcKt.DefinitionTaskServiceCoroutineImplBase import dev.usbharu.owl.broker.domain.model.taskdefinition.TaskDefinition import dev.usbharu.owl.broker.service.RegisterTaskService +import dev.usbharu.owl.generated.DefinitionTask +import dev.usbharu.owl.generated.DefinitionTask.TaskDefined +import dev.usbharu.owl.generated.DefinitionTaskServiceGrpcKt.DefinitionTaskServiceCoroutineImplBase import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/ProducerService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/ProducerService.kt index 47bbb62e..d2157a2d 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/ProducerService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/ProducerService.kt @@ -16,11 +16,11 @@ package dev.usbharu.owl.broker.interfaces.grpc -import dev.usbharu.owl.ProducerOuterClass -import dev.usbharu.owl.ProducerServiceGrpcKt.ProducerServiceCoroutineImplBase import dev.usbharu.owl.broker.external.toUUID import dev.usbharu.owl.broker.service.ProducerService import dev.usbharu.owl.broker.service.RegisterProducerRequest +import dev.usbharu.owl.generated.ProducerOuterClass +import dev.usbharu.owl.generated.ProducerServiceGrpcKt.ProducerServiceCoroutineImplBase import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/SubscribeTaskService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/SubscribeTaskService.kt index 62539d55..d8ed8386 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/SubscribeTaskService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/SubscribeTaskService.kt @@ -16,11 +16,11 @@ package dev.usbharu.owl.broker.interfaces.grpc -import dev.usbharu.owl.Consumer -import dev.usbharu.owl.SubscribeTaskServiceGrpcKt.SubscribeTaskServiceCoroutineImplBase import dev.usbharu.owl.broker.external.toUUID import dev.usbharu.owl.broker.service.ConsumerService import dev.usbharu.owl.broker.service.RegisterConsumerRequest +import dev.usbharu.owl.generated.Consumer +import dev.usbharu.owl.generated.SubscribeTaskServiceGrpcKt.SubscribeTaskServiceCoroutineImplBase import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskPublishService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskPublishService.kt index 10b2154f..8a7bff55 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskPublishService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskPublishService.kt @@ -16,15 +16,15 @@ package dev.usbharu.owl.broker.interfaces.grpc -import dev.usbharu.owl.PublishTaskOuterClass -import dev.usbharu.owl.PublishTaskOuterClass.PublishedTask -import dev.usbharu.owl.PublishTaskOuterClass.PublishedTasks -import dev.usbharu.owl.TaskPublishServiceGrpcKt.TaskPublishServiceCoroutineImplBase import dev.usbharu.owl.broker.external.toUUID import dev.usbharu.owl.broker.service.PublishTask import dev.usbharu.owl.broker.service.TaskPublishService import dev.usbharu.owl.common.property.PropertySerializeUtils import dev.usbharu.owl.common.property.PropertySerializerFactory +import dev.usbharu.owl.generated.PublishTaskOuterClass +import dev.usbharu.owl.generated.PublishTaskOuterClass.PublishedTask +import dev.usbharu.owl.generated.PublishTaskOuterClass.PublishedTasks +import dev.usbharu.owl.generated.TaskPublishServiceGrpcKt.TaskPublishServiceCoroutineImplBase import io.grpc.Status import io.grpc.StatusException import org.slf4j.LoggerFactory diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultService.kt index 90d10f6b..300d3cf5 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultService.kt @@ -17,13 +17,13 @@ package dev.usbharu.owl.broker.interfaces.grpc import com.google.protobuf.Empty -import dev.usbharu.owl.TaskResultOuterClass -import dev.usbharu.owl.TaskResultServiceGrpcKt import dev.usbharu.owl.broker.domain.model.taskresult.TaskResult import dev.usbharu.owl.broker.external.toUUID import dev.usbharu.owl.broker.service.TaskManagementService import dev.usbharu.owl.common.property.PropertySerializeUtils import dev.usbharu.owl.common.property.PropertySerializerFactory +import dev.usbharu.owl.generated.TaskResultOuterClass +import dev.usbharu.owl.generated.TaskResultServiceGrpcKt import io.grpc.Status import io.grpc.StatusException import kotlinx.coroutines.CancellationException diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultSubscribeService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultSubscribeService.kt index e0635d9a..5855cc6d 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultSubscribeService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultSubscribeService.kt @@ -16,11 +16,11 @@ package dev.usbharu.owl.broker.interfaces.grpc -import dev.usbharu.owl.* import dev.usbharu.owl.broker.external.toUUID import dev.usbharu.owl.broker.service.TaskManagementService import dev.usbharu.owl.common.property.PropertySerializeUtils import dev.usbharu.owl.common.property.PropertySerializerFactory +import dev.usbharu.owl.generated.* import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import kotlin.coroutines.CoroutineContext diff --git a/owl/owl-broker/src/main/proto/consumer.proto b/owl/owl-broker/src/main/proto/consumer.proto index 252d4a27..8ded7398 100644 --- a/owl/owl-broker/src/main/proto/consumer.proto +++ b/owl/owl-broker/src/main/proto/consumer.proto @@ -1,7 +1,7 @@ syntax = "proto3"; import "uuid.proto"; -option java_package = "dev.usbharu.owl"; +option java_package = "dev.usbharu.owl.generated"; message SubscribeTaskRequest { string name = 1; diff --git a/owl/owl-broker/src/main/proto/definition_task.proto b/owl/owl-broker/src/main/proto/definition_task.proto index 6cab5257..1e7b63f7 100644 --- a/owl/owl-broker/src/main/proto/definition_task.proto +++ b/owl/owl-broker/src/main/proto/definition_task.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -option java_package = "dev.usbharu.owl"; +option java_package = "dev.usbharu.owl.generated"; import "google/protobuf/empty.proto"; import "uuid.proto"; diff --git a/owl/owl-broker/src/main/proto/producer.proto b/owl/owl-broker/src/main/proto/producer.proto index b4bbcd7a..7f3e9f05 100644 --- a/owl/owl-broker/src/main/proto/producer.proto +++ b/owl/owl-broker/src/main/proto/producer.proto @@ -2,7 +2,7 @@ syntax = "proto3"; import "uuid.proto"; -option java_package = "dev.usbharu.owl"; +option java_package = "dev.usbharu.owl.generated"; message Producer { string name = 1; diff --git a/owl/owl-broker/src/main/proto/property.proto b/owl/owl-broker/src/main/proto/property.proto index 138e7e22..bb1f5d48 100644 --- a/owl/owl-broker/src/main/proto/property.proto +++ b/owl/owl-broker/src/main/proto/property.proto @@ -2,7 +2,7 @@ syntax = "proto3"; import "google/protobuf/empty.proto"; -option java_package = "dev.usbharu.owl"; +option java_package = "dev.usbharu.owl.generated"; message Property{ oneof value { diff --git a/owl/owl-broker/src/main/proto/publish_task.proto b/owl/owl-broker/src/main/proto/publish_task.proto index 620e6396..db3292e8 100644 --- a/owl/owl-broker/src/main/proto/publish_task.proto +++ b/owl/owl-broker/src/main/proto/publish_task.proto @@ -4,7 +4,7 @@ import "google/protobuf/timestamp.proto"; import "uuid.proto"; -option java_package = "dev.usbharu.owl"; +option java_package = "dev.usbharu.owl.generated"; message PublishTask { diff --git a/owl/owl-broker/src/main/proto/task.proto b/owl/owl-broker/src/main/proto/task.proto index 48566fdb..7e2621bc 100644 --- a/owl/owl-broker/src/main/proto/task.proto +++ b/owl/owl-broker/src/main/proto/task.proto @@ -3,7 +3,7 @@ import "uuid.proto"; import "google/protobuf/timestamp.proto"; import "property.proto"; -option java_package = "dev.usbharu.owl"; +option java_package = "dev.usbharu.owl.generated"; message ReadyRequest { int32 number_of_concurrent = 1; diff --git a/owl/owl-broker/src/main/proto/task_result.proto b/owl/owl-broker/src/main/proto/task_result.proto index 642f7425..a6a74b9a 100644 --- a/owl/owl-broker/src/main/proto/task_result.proto +++ b/owl/owl-broker/src/main/proto/task_result.proto @@ -3,7 +3,7 @@ import "uuid.proto"; import "google/protobuf/empty.proto"; import "property.proto"; -option java_package = "dev.usbharu.owl"; +option java_package = "dev.usbharu.owl.generated"; message TaskResult { UUID id = 1; diff --git a/owl/owl-broker/src/main/proto/task_result_producer.proto b/owl/owl-broker/src/main/proto/task_result_producer.proto index 6102a020..ac6169eb 100644 --- a/owl/owl-broker/src/main/proto/task_result_producer.proto +++ b/owl/owl-broker/src/main/proto/task_result_producer.proto @@ -2,7 +2,7 @@ syntax = "proto3"; import "uuid.proto"; import "task_result.proto"; -option java_package = "dev.usbharu.owl"; +option java_package = "dev.usbharu.owl.generated"; message TaskResults { string name = 1; diff --git a/owl/owl-broker/src/main/proto/uuid.proto b/owl/owl-broker/src/main/proto/uuid.proto index 26d61001..1dca5916 100644 --- a/owl/owl-broker/src/main/proto/uuid.proto +++ b/owl/owl-broker/src/main/proto/uuid.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -option java_package = "dev.usbharu.owl"; +option java_package = "dev.usbharu.owl.generated"; message UUID { uint64 most_significant_uuid_bits = 1; diff --git a/owl/owl-consumer/build.gradle.kts b/owl/owl-consumer/build.gradle.kts index 403f8c88..f629d302 100644 --- a/owl/owl-consumer/build.gradle.kts +++ b/owl/owl-consumer/build.gradle.kts @@ -33,7 +33,7 @@ protobuf { artifact = libs.protoc.gen.grpc.java.get().toString() } create("grpckt") { - artifact = libs.protoc.gen.grpc.kotlin.get().toString() + "jdk8@jar" + artifact = libs.protoc.gen.grpc.kotlin.get().toString() + ":jdk8@jar" } } generateProtoTasks { diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Consumer.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Consumer.kt index 56ac00c7..ee925335 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Consumer.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Consumer.kt @@ -16,10 +16,10 @@ package dev.usbharu.owl.consumer -import dev.usbharu.owl.* -import dev.usbharu.owl.Uuid.UUID import dev.usbharu.owl.common.property.PropertySerializeUtils import dev.usbharu.owl.common.property.PropertySerializerFactory +import dev.usbharu.owl.generated.* +import dev.usbharu.owl.generated.Uuid.UUID import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import org.slf4j.LoggerFactory diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumer.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumer.kt index 34f75a05..a9b42635 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumer.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumer.kt @@ -16,11 +16,11 @@ package dev.usbharu.owl.consumer -import dev.usbharu.owl.AssignmentTaskServiceGrpcKt -import dev.usbharu.owl.SubscribeTaskServiceGrpcKt -import dev.usbharu.owl.TaskResultServiceGrpcKt import dev.usbharu.owl.common.property.CustomPropertySerializerFactory import dev.usbharu.owl.common.property.PropertySerializerFactory +import dev.usbharu.owl.generated.AssignmentTaskServiceGrpcKt +import dev.usbharu.owl.generated.SubscribeTaskServiceGrpcKt +import dev.usbharu.owl.generated.TaskResultServiceGrpcKt import io.grpc.ManagedChannelBuilder import java.nio.file.Path diff --git a/owl/owl-producer/owl-producer-default/build.gradle.kts b/owl/owl-producer/owl-producer-default/build.gradle.kts index 7994b7f9..d4d4fe15 100644 --- a/owl/owl-producer/owl-producer-default/build.gradle.kts +++ b/owl/owl-producer/owl-producer-default/build.gradle.kts @@ -34,7 +34,7 @@ protobuf { artifact = libs.protoc.gen.grpc.java.get().toString() } create("grpckt") { - artifact = libs.protoc.gen.grpc.kotlin.get().toString() + "jdk8@jar" + artifact = libs.protoc.gen.grpc.kotlin.get().toString() + ":jdk8@jar" } } generateProtoTasks { diff --git a/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducer.kt b/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducer.kt index e4a1dfd4..065eb28e 100644 --- a/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducer.kt +++ b/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducer.kt @@ -17,12 +17,12 @@ package dev.usbharu.owl.producer.defaultimpl import com.google.protobuf.timestamp -import dev.usbharu.owl.* -import dev.usbharu.owl.Uuid.UUID import dev.usbharu.owl.common.property.PropertySerializeUtils import dev.usbharu.owl.common.task.PublishedTask import dev.usbharu.owl.common.task.Task import dev.usbharu.owl.common.task.TaskDefinition +import dev.usbharu.owl.generated.* +import dev.usbharu.owl.generated.Uuid.UUID import dev.usbharu.owl.producer.api.OwlProducer import java.time.Instant @@ -69,7 +69,7 @@ class DefaultOwlProducer(private val defaultOwlProducerConfig: DefaultOwlProduce ) val now = Instant.now() val publishTask = taskPublishServiceCoroutineStub.publishTask( - dev.usbharu.owl.publishTask { + dev.usbharu.owl.generated.publishTask { this.producerId = this@DefaultOwlProducer.producerId this.publishedAt = timestamp { diff --git a/settings.gradle.kts b/settings.gradle.kts index 8c6faaff..dca54015 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,6 +21,7 @@ rootProject.name = "hideout" includeBuild("hideout-core") includeBuild("hideout-mastodon") +includeBuild("hideout-activitypub") dependencyResolutionManagement { repositories { From 1a2142e83b2b3101760d191f74c9e448068caed5 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 21:53:54 +0900 Subject: [PATCH 32/56] =?UTF-8?q?chore:=E3=80=80owl=E3=81=A7detekt?= =?UTF-8?q?=E3=81=8C=E5=8B=95=E4=BD=9C=E3=81=99=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 -- hideout-activitypub/build.gradle.kts | 1 - owl/build.gradle.kts | 21 +++++++++++++++++++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 52f8a2b7..ee19d44a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,3 @@ -import dev.usbharu.hideout.core.infrastructure.exposedrepository.UserDetails.password - /* * Copyright (C) 2024 usbharu * diff --git a/hideout-activitypub/build.gradle.kts b/hideout-activitypub/build.gradle.kts index 6a2d223a..8c14e9a6 100644 --- a/hideout-activitypub/build.gradle.kts +++ b/hideout-activitypub/build.gradle.kts @@ -1,4 +1,3 @@ -import dev.usbharu.hideout.core.infrastructure.exposedrepository.Instance.version import kotlinx.kover.gradle.plugin.dsl.CoverageUnit plugins { diff --git a/owl/build.gradle.kts b/owl/build.gradle.kts index 066d8b10..5ea6ae9e 100644 --- a/owl/build.gradle.kts +++ b/owl/build.gradle.kts @@ -32,6 +32,7 @@ subprojects { plugin("org.jetbrains.kotlin.jvm") plugin("maven-publish") plugin(rootProject.libs.plugins.kover.get().pluginId) + plugin(rootProject.libs.plugins.detekt.get().pluginId) } kotlin { jvmToolchain(21) @@ -40,9 +41,19 @@ subprojects { dependencies { implementation("org.slf4j:slf4j-api:2.0.15") testImplementation("org.junit.jupiter:junit-jupiter:5.10.3") - + detektPlugins(rootProject.libs.detekt.formatting) } + + detekt { + parallel = true + config.setFrom(files("$rootDir/../detekt.yml")) + buildUponDefaultConfig = true + basePath = "${projectDir}/src/main/kotlin" + autoCorrect = true + } + + project.gradle.taskGraph.whenReady { if (this.hasTask(":koverGenerateArtifact")) { val task = this.allTasks.find { println(it.name);it.name == "test" } @@ -94,7 +105,13 @@ dependencies { kover(project(":owl-producer:owl-producer-embedded")) } - +detekt { + parallel = true + config.setFrom(files("../detekt.yml")) + buildUponDefaultConfig = true + basePath = "${projectDir}/src/main/kotlin" + autoCorrect = true +} project.gradle.taskGraph.whenReady { if (this.hasTask(":koverGenerateArtifact")) { From 4bc9e3abd28cff8e8e9f7867a72685bb0c39dc67 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 22:02:29 +0900 Subject: [PATCH 33/56] style: fix lint --- owl/build.gradle.kts | 20 +- .../owl/broker/mongodb/MongoModuleContext.kt | 4 +- .../mongodb/MongodbConsumerRepository.kt | 22 ++- .../mongodb/MongodbProducerRepository.kt | 2 +- .../mongodb/MongodbQueuedTaskRepository.kt | 42 ++--- .../MongodbTaskDefinitionRepository.kt | 4 +- .../broker/mongodb/MongodbTaskRepository.kt | 43 +++-- .../mongodb/MongodbTaskResultRepository.kt | 35 ++-- .../kotlin/dev/usbharu/owl/broker/Main.kt | 4 +- .../dev/usbharu/owl/broker/ModuleContext.kt | 8 +- .../owl/broker/OwlBrokerApplication.kt | 5 +- .../exception/InvalidRepositoryException.kt | 2 +- .../repository/FailedSaveException.kt | 2 +- .../repository/RecordNotFoundException.kt | 2 +- .../service/IncompatibleTaskException.kt | 2 +- .../service/QueueCannotDequeueException.kt | 2 +- .../service/TaskNotRegisterException.kt | 2 +- .../model/consumer/ConsumerRepository.kt | 6 +- .../broker/domain/model/producer/Producer.kt | 8 +- .../model/producer/ProducerRepository.kt | 4 +- .../model/queuedtask/QueuedTaskRepository.kt | 6 +- .../owl/broker/domain/model/task/Task.kt | 6 +- .../domain/model/task/TaskRepository.kt | 12 +- .../model/taskdefinition/TaskDefinition.kt | 2 +- .../TaskDefinitionRepository.kt | 6 +- .../domain/model/taskresult/TaskResult.kt | 2 +- .../model/taskresult/TaskResultRepository.kt | 6 +- .../owl/broker/external/GrpcExtension.kt | 2 +- .../interfaces/grpc/AssignmentTaskService.kt | 5 +- .../interfaces/grpc/DefinitionTaskService.kt | 19 +- .../broker/interfaces/grpc/ProducerService.kt | 10 +- .../interfaces/grpc/SubscribeTaskService.kt | 2 +- .../interfaces/grpc/TaskPublishService.kt | 7 +- .../interfaces/grpc/TaskResultService.kt | 2 +- .../grpc/TaskResultSubscribeService.kt | 20 +- .../broker/service/AssignQueuedTaskDecider.kt | 4 +- .../owl/broker/service/ConsumerService.kt | 2 +- .../DefaultPropertySerializerFactory.kt | 2 +- .../owl/broker/service/ProducerService.kt | 4 +- .../owl/broker/service/QueueScanner.kt | 19 +- .../usbharu/owl/broker/service/QueueStore.kt | 21 +-- .../owl/broker/service/QueuedTaskAssigner.kt | 4 +- .../owl/broker/service/RegisterTaskService.kt | 15 +- .../broker/service/TaskManagementService.kt | 12 +- .../owl/broker/service/TaskPublishService.kt | 19 +- .../usbharu/owl/broker/service/TaskResults.kt | 8 +- .../usbharu/owl/broker/service/TaskScanner.kt | 2 +- .../src/main/kotlin/dev/usbharu/Main.kt | 2 +- .../common/property/ObjectPropertyValue.kt | 3 +- .../dev/usbharu/owl/common/ReflectionUtils.kt | 5 +- .../common/property/BooleanPropertyValue.kt | 19 +- .../CustomPropertySerializerFactory.kt | 11 +- .../common/property/DoublePropertyValue.kt | 19 +- .../owl/common/property/FloatPropertyValue.kt | 19 +- .../common/property/IntegerPropertyValue.kt | 19 +- .../owl/common/property/LongPropertyValue.kt | 19 +- .../property/PropertySerializeException.kt | 2 +- .../common/property/PropertySerializeUtils.kt | 2 +- .../owl/common/property/PropertySerializer.kt | 2 +- .../property/PropertySerializerFactory.kt | 2 +- .../owl/common/property/PropertyType.kt | 2 +- .../owl/common/property/PropertyValue.kt | 8 +- .../common/property/StringPropertyValue.kt | 18 +- .../common/retry/ExponentialRetryPolicy.kt | 3 +- .../usbharu/owl/common/retry/RetryPolicy.kt | 2 +- .../owl/common/retry/RetryPolicyFactory.kt | 7 +- .../retry/RetryPolicyNotFoundException.kt | 2 +- .../owl/common/task/PropertyDefinition.kt | 2 - .../usbharu/owl/common/task/PublishedTask.kt | 2 +- .../dev/usbharu/owl/common/task/Task.kt | 2 +- .../usbharu/owl/common/task/TaskDefinition.kt | 3 +- .../owl/consumer/AbstractTaskRunner.kt | 3 +- .../dev/usbharu/owl/consumer/Consumer.kt | 171 ++++++++++-------- .../kotlin/dev/usbharu/owl/consumer/Main.kt | 3 +- .../consumer/ServiceLoaderTaskRunnerLoader.kt | 2 +- .../owl/consumer/StandaloneConsumer.kt | 11 +- .../StandaloneConsumerConfigLoader.kt | 2 +- .../dev/usbharu/owl/consumer/TaskRequest.kt | 8 +- .../dev/usbharu/owl/consumer/TaskResult.kt | 2 +- .../dev/usbharu/owl/consumer/TaskRunner.kt | 2 +- .../usbharu/owl/consumer/TaskRunnerLoader.kt | 2 +- .../owl/producer/api/OwlProducerBuilder.kt | 2 +- .../producer/api/OwlProducerBuilderConfig.kt | 2 +- .../owl/producer/api/OwlProducerConfig.kt | 2 +- .../defaultimpl/DefaultOwlProducer.kt | 33 ++-- .../defaultimpl/DefaultOwlProducerBuilder.kt | 2 +- .../defaultimpl/DefaultOwlProducerConfig.kt | 2 +- .../embedded/EmbeddedGrpcOwlProducer.kt | 2 +- .../EmbeddedGrpcOwlProducerBuilder.kt | 2 +- .../embedded/EmbeddedGrpcOwlProducerConfig.kt | 2 +- .../producer/embedded/EmbeddedOwlProducer.kt | 3 +- .../embedded/EmbeddedOwlProducerBuilder.kt | 3 +- 92 files changed, 413 insertions(+), 461 deletions(-) diff --git a/owl/build.gradle.kts b/owl/build.gradle.kts index 5ea6ae9e..5443b6b6 100644 --- a/owl/build.gradle.kts +++ b/owl/build.gradle.kts @@ -53,7 +53,6 @@ subprojects { autoCorrect = true } - project.gradle.taskGraph.whenReady { if (this.hasTask(":koverGenerateArtifact")) { val task = this.allTasks.find { println(it.name);it.name == "test" } @@ -61,8 +60,23 @@ subprojects { verificationTask.ignoreFailures = true } } - tasks.test { - useJUnitPlatform() + tasks { + withType { + exclude("**/generated/**") + setSource("src/main/kotlin") + exclude("build/") + configureEach { + exclude("**/org/koin/ksp/generated/**", "**/generated/**") + } + } + withType() { + configureEach { + exclude("**/org/koin/ksp/generated/**", "**/generated/**") + } + } + withType { + useJUnitPlatform() + } } publishing { diff --git a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongoModuleContext.kt b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongoModuleContext.kt index 5c1af4fb..472207ea 100644 --- a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongoModuleContext.kt +++ b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongoModuleContext.kt @@ -32,7 +32,6 @@ import org.koin.dsl.module class MongoModuleContext : ModuleContext { override fun module(): Module { - return module { single { val clientSettings = @@ -47,7 +46,6 @@ class MongoModuleContext : ModuleContext { ) .uuidRepresentation(UuidRepresentation.STANDARD).build() - MongoClient.create(clientSettings) .getDatabase(System.getProperty("owl.broker.mongo.database", "mongo-test")) } @@ -59,4 +57,4 @@ class MongoModuleContext : ModuleContext { single { MongodbTaskResultRepository(get(), get()) } } } -} \ No newline at end of file +} diff --git a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbConsumerRepository.kt b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbConsumerRepository.kt index 4310b956..3d4eef8d 100644 --- a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbConsumerRepository.kt +++ b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbConsumerRepository.kt @@ -33,7 +33,11 @@ class MongodbConsumerRepository(database: MongoDatabase) : ConsumerRepository { private val collection = database.getCollection("consumers") override suspend fun save(consumer: Consumer): Consumer = withContext(Dispatchers.IO) { - collection.replaceOne(Filters.eq("_id", consumer.id.toString()), ConsumerMongodb.of(consumer), ReplaceOptions().upsert(true)) + collection.replaceOne( + Filters.eq("_id", consumer.id.toString()), + ConsumerMongodb.of(consumer), + ReplaceOptions().upsert(true) + ) return@withContext consumer } @@ -49,15 +53,19 @@ data class ConsumerMongodb( val name: String, val hostname: String, val tasks: List -){ +) { - fun toConsumer():Consumer{ + fun toConsumer(): Consumer { return Consumer( - UUID.fromString(id), name, hostname, tasks + UUID.fromString(id), + name, + hostname, + tasks ) } - companion object{ - fun of(consumer: Consumer):ConsumerMongodb{ + + companion object { + fun of(consumer: Consumer): ConsumerMongodb { return ConsumerMongodb( consumer.id.toString(), consumer.name, @@ -66,4 +74,4 @@ data class ConsumerMongodb( ) } } -} \ No newline at end of file +} diff --git a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbProducerRepository.kt b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbProducerRepository.kt index 76d9a755..6fba0352 100644 --- a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbProducerRepository.kt +++ b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbProducerRepository.kt @@ -68,4 +68,4 @@ data class ProducerMongodb( ) } } -} \ No newline at end of file +} diff --git a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbQueuedTaskRepository.kt b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbQueuedTaskRepository.kt index 833baca9..720ac9dc 100644 --- a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbQueuedTaskRepository.kt +++ b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbQueuedTaskRepository.kt @@ -48,7 +48,8 @@ class MongodbQueuedTaskRepository( override suspend fun save(queuedTask: QueuedTask): QueuedTask { withContext(Dispatchers.IO) { collection.replaceOne( - eq("_id", queuedTask.task.id.toString()), QueuedTaskMongodb.of(propertySerializerFactory, queuedTask), + eq("_id", queuedTask.task.id.toString()), + QueuedTaskMongodb.of(propertySerializerFactory, queuedTask), ReplaceOptions().upsert(true) ) } @@ -57,7 +58,6 @@ class MongodbQueuedTaskRepository( override suspend fun findByTaskIdAndAssignedConsumerIsNullAndUpdate(id: UUID, update: QueuedTask): QueuedTask { return withContext(Dispatchers.IO) { - val findOneAndUpdate = collection.findOneAndUpdate( and( eq("_id", id.toString()), @@ -108,7 +108,7 @@ data class QueuedTaskMongodb( val task: TaskMongodb, val attempt: Int, val queuedAt: Instant, - val priority:Int, + val priority: Int, val isActive: Boolean, val timeoutAt: Instant?, val assignedConsumer: String?, @@ -155,14 +155,14 @@ data class QueuedTaskMongodb( companion object { fun of(propertySerializerFactory: PropertySerializerFactory, task: Task): TaskMongodb { return TaskMongodb( - task.name, - task.id.toString(), - task.publishProducerId.toString(), - task.publishedAt, - task.nextRetry, - task.completedAt, - task.attempt, - PropertySerializeUtils.serialize(propertySerializerFactory, task.properties) + name = task.name, + id = task.id.toString(), + publishProducerId = task.publishProducerId.toString(), + publishedAt = task.publishedAt, + nextRetry = task.nextRetry, + completedAt = task.completedAt, + attempt = task.attempt, + properties = PropertySerializeUtils.serialize(propertySerializerFactory, task.properties) ) } } @@ -171,16 +171,16 @@ data class QueuedTaskMongodb( companion object { fun of(propertySerializerFactory: PropertySerializerFactory, queuedTask: QueuedTask): QueuedTaskMongodb { return QueuedTaskMongodb( - queuedTask.task.id.toString(), - TaskMongodb.of(propertySerializerFactory, queuedTask.task), - queuedTask.attempt, - queuedTask.queuedAt, - queuedTask.priority, - queuedTask.isActive, - queuedTask.timeoutAt, - queuedTask.assignedConsumer?.toString(), - queuedTask.assignedAt + id = queuedTask.task.id.toString(), + task = TaskMongodb.of(propertySerializerFactory, queuedTask.task), + attempt = queuedTask.attempt, + queuedAt = queuedTask.queuedAt, + priority = queuedTask.priority, + isActive = queuedTask.isActive, + timeoutAt = queuedTask.timeoutAt, + assignedConsumer = queuedTask.assignedConsumer?.toString(), + assignedAt = queuedTask.assignedAt ) } } -} \ No newline at end of file +} diff --git a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskDefinitionRepository.kt b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskDefinitionRepository.kt index f3b384a1..e51177cc 100644 --- a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskDefinitionRepository.kt +++ b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskDefinitionRepository.kt @@ -41,7 +41,7 @@ class MongodbTaskDefinitionRepository(database: MongoDatabase) : TaskDefinitionR } override suspend fun deleteByName(name: String): Unit = withContext(Dispatchers.IO) { - collection.deleteOne(Filters.eq("_id",name)) + collection.deleteOne(Filters.eq("_id", name)) } override suspend fun findByName(name: String): TaskDefinition? = withContext(Dispatchers.IO) { @@ -82,4 +82,4 @@ data class TaskDefinitionMongodb( ) } } -} \ No newline at end of file +} diff --git a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskRepository.kt b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskRepository.kt index 2745b0cd..e0299652 100644 --- a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskRepository.kt +++ b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskRepository.kt @@ -36,27 +36,29 @@ import org.bson.codecs.pojo.annotations.BsonRepresentation import java.time.Instant import java.util.* - class MongodbTaskRepository(database: MongoDatabase, private val propertySerializerFactory: PropertySerializerFactory) : TaskRepository { private val collection = database.getCollection("tasks") override suspend fun save(task: Task): Task = withContext(Dispatchers.IO) { collection.replaceOne( - Filters.eq("_id", task.id.toString()), TaskMongodb.of(propertySerializerFactory, task), + Filters.eq("_id", task.id.toString()), + TaskMongodb.of(propertySerializerFactory, task), ReplaceOptions().upsert(true) ) return@withContext task } override suspend fun saveAll(tasks: List): Unit = withContext(Dispatchers.IO) { - collection.bulkWrite(tasks.map { - ReplaceOneModel( - Filters.eq(it.id.toString()), - TaskMongodb.of(propertySerializerFactory, it), - ReplaceOptions().upsert(true) - ) - }) + collection.bulkWrite( + tasks.map { + ReplaceOneModel( + Filters.eq(it.id.toString()), + TaskMongodb.of(propertySerializerFactory, it), + ReplaceOptions().upsert(true) + ) + } + ) } override fun findByNextRetryBeforeAndCompletedAtIsNull(timestamp: Instant): Flow { @@ -75,12 +77,13 @@ class MongodbTaskRepository(database: MongoDatabase, private val propertySeriali override suspend fun findByIdAndUpdate(id: UUID, task: Task) { collection.replaceOne( - Filters.eq("_id", task.id.toString()), TaskMongodb.of(propertySerializerFactory, task), + Filters.eq("_id", task.id.toString()), + TaskMongodb.of(propertySerializerFactory, task), ReplaceOptions().upsert(false) ) } - override suspend fun findByPublishProducerIdAndCompletedAtIsNotNull(publishProducerId: UUID): Flow { + override fun findByPublishProducerIdAndCompletedAtIsNotNull(publishProducerId: UUID): Flow { return collection .find(Filters.eq(TaskMongodb::publishProducerId.name, publishProducerId.toString())) .map { it.toTask(propertySerializerFactory) } @@ -116,15 +119,15 @@ data class TaskMongodb( companion object { fun of(propertySerializerFactory: PropertySerializerFactory, task: Task): TaskMongodb { return TaskMongodb( - task.name, - task.id.toString(), - task.publishProducerId.toString(), - task.publishedAt, - task.nextRetry, - task.completedAt, - task.attempt, - PropertySerializeUtils.serialize(propertySerializerFactory, task.properties) + name = task.name, + id = task.id.toString(), + publishProducerId = task.publishProducerId.toString(), + publishedAt = task.publishedAt, + nextRetry = task.nextRetry, + completedAt = task.completedAt, + attempt = task.attempt, + properties = PropertySerializeUtils.serialize(propertySerializerFactory, task.properties) ) } } -} \ No newline at end of file +} diff --git a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskResultRepository.kt b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskResultRepository.kt index 2336a45c..cc671a65 100644 --- a/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskResultRepository.kt +++ b/owl/owl-broker/owl-broker-mongodb/src/main/kotlin/dev/usbharu/owl/broker/mongodb/MongodbTaskResultRepository.kt @@ -41,14 +41,17 @@ class MongodbTaskResultRepository( private val collection = database.getCollection("task_results") override suspend fun save(taskResult: TaskResult): TaskResult = withContext(Dispatchers.IO) { collection.replaceOne( - Filters.eq(taskResult.id.toString()), TaskResultMongodb.of(propertySerializerFactory, taskResult), + Filters.eq(taskResult.id.toString()), + TaskResultMongodb.of(propertySerializerFactory, taskResult), ReplaceOptions().upsert(true) ) return@withContext taskResult } override fun findByTaskId(id: UUID): Flow { - return collection.find(Filters.eq(id.toString())).map { it.toTaskResult(propertySerializerFactory) }.flowOn(Dispatchers.IO) + return collection.find( + Filters.eq(id.toString()) + ).map { it.toTaskResult(propertySerializerFactory) }.flowOn(Dispatchers.IO) } } @@ -65,27 +68,25 @@ data class TaskResultMongodb( fun toTaskResult(propertySerializerFactory: PropertySerializerFactory): TaskResult { return TaskResult( - UUID.fromString(id), - UUID.fromString(taskId), - success, - attempt, - PropertySerializeUtils.deserialize(propertySerializerFactory, result), - message + id = UUID.fromString(id), + taskId = UUID.fromString(taskId), + success = success, + attempt = attempt, + result = PropertySerializeUtils.deserialize(propertySerializerFactory, result), + message = message ) } companion object { fun of(propertySerializerFactory: PropertySerializerFactory, taskResult: TaskResult): TaskResultMongodb { return TaskResultMongodb( - taskResult.id.toString(), - taskResult.taskId.toString(), - taskResult.success, - taskResult.attempt, - PropertySerializeUtils.serialize(propertySerializerFactory, taskResult.result), - taskResult.message + id = taskResult.id.toString(), + taskId = taskResult.taskId.toString(), + success = taskResult.success, + attempt = taskResult.attempt, + result = PropertySerializeUtils.serialize(propertySerializerFactory, taskResult.result), + message = taskResult.message ) - } - } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/Main.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/Main.kt index d5f25364..2a0ebb1f 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/Main.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/Main.kt @@ -90,7 +90,6 @@ fun main() { logger.info("Use module name: {}", moduleContext) - val koin = startKoin { printLogger() @@ -98,7 +97,6 @@ fun main() { single { DefaultRetryPolicyFactory(mapOf("" to ExponentialRetryPolicy())) } - } modules(mainModule, module, moduleContext.module()) } @@ -108,4 +106,4 @@ fun main() { runBlocking { application.start(50051).join() } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/ModuleContext.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/ModuleContext.kt index fbb32f7c..a75dffb3 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/ModuleContext.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/ModuleContext.kt @@ -19,11 +19,9 @@ package dev.usbharu.owl.broker import org.koin.core.module.Module interface ModuleContext { - fun module():Module + fun module(): Module } data object EmptyModuleContext : ModuleContext { - override fun module(): Module { - return org.koin.dsl.module { } - } -} \ No newline at end of file + override fun module(): Module = org.koin.dsl.module { } +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/OwlBrokerApplication.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/OwlBrokerApplication.kt index a67661ca..96b824ce 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/OwlBrokerApplication.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/OwlBrokerApplication.kt @@ -38,7 +38,7 @@ class OwlBrokerApplication( private lateinit var server: Server - fun start(port: Int,coroutineScope: CoroutineScope = GlobalScope):Job { + fun start(port: Int, coroutineScope: CoroutineScope = GlobalScope): Job { server = ServerBuilder.forPort(port) .addService(assignmentTaskService) .addService(definitionTaskService) @@ -64,5 +64,4 @@ class OwlBrokerApplication( fun stop() { server.shutdown() } - -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/InvalidRepositoryException.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/InvalidRepositoryException.kt index 9019c314..a48232fa 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/InvalidRepositoryException.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/InvalidRepositoryException.kt @@ -27,4 +27,4 @@ class InvalidRepositoryException : RuntimeException { enableSuppression, writableStackTrace ) -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/repository/FailedSaveException.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/repository/FailedSaveException.kt index 4cb68305..782ac6ab 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/repository/FailedSaveException.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/repository/FailedSaveException.kt @@ -27,4 +27,4 @@ class FailedSaveException : RuntimeException { enableSuppression, writableStackTrace ) -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/repository/RecordNotFoundException.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/repository/RecordNotFoundException.kt index 62921c46..2a28a662 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/repository/RecordNotFoundException.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/repository/RecordNotFoundException.kt @@ -27,4 +27,4 @@ open class RecordNotFoundException : RuntimeException { enableSuppression, writableStackTrace ) -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/IncompatibleTaskException.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/IncompatibleTaskException.kt index 9f940bc2..54fe2717 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/IncompatibleTaskException.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/IncompatibleTaskException.kt @@ -27,4 +27,4 @@ class IncompatibleTaskException : RuntimeException { enableSuppression, writableStackTrace ) -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/QueueCannotDequeueException.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/QueueCannotDequeueException.kt index 49b47dbf..c89df8cc 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/QueueCannotDequeueException.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/QueueCannotDequeueException.kt @@ -27,4 +27,4 @@ class QueueCannotDequeueException : RuntimeException { enableSuppression, writableStackTrace ) -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/TaskNotRegisterException.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/TaskNotRegisterException.kt index ca894165..bc134711 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/TaskNotRegisterException.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/exception/service/TaskNotRegisterException.kt @@ -27,4 +27,4 @@ class TaskNotRegisterException : RuntimeException { enableSuppression, writableStackTrace ) -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/consumer/ConsumerRepository.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/consumer/ConsumerRepository.kt index 34ebb0af..47289625 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/consumer/ConsumerRepository.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/consumer/ConsumerRepository.kt @@ -19,7 +19,7 @@ package dev.usbharu.owl.broker.domain.model.consumer import java.util.* interface ConsumerRepository { - suspend fun save(consumer: Consumer):Consumer + suspend fun save(consumer: Consumer): Consumer - suspend fun findById(id:UUID):Consumer? -} \ No newline at end of file + suspend fun findById(id: UUID): Consumer? +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/producer/Producer.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/producer/Producer.kt index eebbafd4..4bf96d77 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/producer/Producer.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/producer/Producer.kt @@ -20,9 +20,9 @@ import java.time.Instant import java.util.* data class Producer( - val id:UUID, - val name:String, - val hostname:String, - val registeredTask:List, + val id: UUID, + val name: String, + val hostname: String, + val registeredTask: List, val createdAt: Instant ) diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/producer/ProducerRepository.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/producer/ProducerRepository.kt index 932cef10..67aff038 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/producer/ProducerRepository.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/producer/ProducerRepository.kt @@ -17,5 +17,5 @@ package dev.usbharu.owl.broker.domain.model.producer interface ProducerRepository { - suspend fun save(producer: Producer):Producer -} \ No newline at end of file + suspend fun save(producer: Producer): Producer +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/queuedtask/QueuedTaskRepository.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/queuedtask/QueuedTaskRepository.kt index 9f3c12a7..0382eff9 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/queuedtask/QueuedTaskRepository.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/queuedtask/QueuedTaskRepository.kt @@ -21,14 +21,14 @@ import java.time.Instant import java.util.* interface QueuedTaskRepository { - suspend fun save(queuedTask: QueuedTask):QueuedTask + suspend fun save(queuedTask: QueuedTask): QueuedTask /** * トランザクションの代わり */ - suspend fun findByTaskIdAndAssignedConsumerIsNullAndUpdate(id:UUID,update:QueuedTask):QueuedTask + suspend fun findByTaskIdAndAssignedConsumerIsNullAndUpdate(id: UUID, update: QueuedTask): QueuedTask fun findByTaskNameInAndIsActiveIsTrueAndOrderByPriority(tasks: List, limit: Int): Flow fun findByQueuedAtBeforeAndIsActiveIsTrue(instant: Instant): Flow -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/task/Task.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/task/Task.kt index 8bf3a162..03dfb63f 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/task/Task.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/task/Task.kt @@ -24,11 +24,11 @@ import java.util.* * @param attempt 失敗を含めて試行した回数 */ data class Task( - val name:String, + val name: String, val id: UUID, - val publishProducerId:UUID, + val publishProducerId: UUID, val publishedAt: Instant, - val nextRetry:Instant, + val nextRetry: Instant, val completedAt: Instant? = null, val attempt: Int, val properties: Map> diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/task/TaskRepository.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/task/TaskRepository.kt index 009dea2d..6f6294db 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/task/TaskRepository.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/task/TaskRepository.kt @@ -21,15 +21,15 @@ import java.time.Instant import java.util.* interface TaskRepository { - suspend fun save(task: Task):Task + suspend fun save(task: Task): Task - suspend fun saveAll(tasks:List) + suspend fun saveAll(tasks: List) - fun findByNextRetryBeforeAndCompletedAtIsNull(timestamp:Instant): Flow + fun findByNextRetryBeforeAndCompletedAtIsNull(timestamp: Instant): Flow suspend fun findById(uuid: UUID): Task? - suspend fun findByIdAndUpdate(id:UUID,task: Task) + suspend fun findByIdAndUpdate(id: UUID, task: Task) - suspend fun findByPublishProducerIdAndCompletedAtIsNotNull(publishProducerId:UUID):Flow -} \ No newline at end of file + fun findByPublishProducerIdAndCompletedAtIsNotNull(publishProducerId: UUID): Flow +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskdefinition/TaskDefinition.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskdefinition/TaskDefinition.kt index 8fcb8f1e..a775d727 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskdefinition/TaskDefinition.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskdefinition/TaskDefinition.kt @@ -22,5 +22,5 @@ data class TaskDefinition( val maxRetry: Int, val timeoutMilli: Long, val propertyDefinitionHash: Long, - val retryPolicy:String + val retryPolicy: String ) diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskdefinition/TaskDefinitionRepository.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskdefinition/TaskDefinitionRepository.kt index 2a1c3c6a..185a70a5 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskdefinition/TaskDefinitionRepository.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskdefinition/TaskDefinitionRepository.kt @@ -18,7 +18,7 @@ package dev.usbharu.owl.broker.domain.model.taskdefinition interface TaskDefinitionRepository { suspend fun save(taskDefinition: TaskDefinition): TaskDefinition - suspend fun deleteByName(name:String) + suspend fun deleteByName(name: String) - suspend fun findByName(name:String):TaskDefinition? -} \ No newline at end of file + suspend fun findByName(name: String): TaskDefinition? +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskresult/TaskResult.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskresult/TaskResult.kt index b024d04c..b2480e65 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskresult/TaskResult.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskresult/TaskResult.kt @@ -21,7 +21,7 @@ import java.util.* data class TaskResult( val id: UUID, - val taskId:UUID, + val taskId: UUID, val success: Boolean, val attempt: Int, val result: Map>, diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskresult/TaskResultRepository.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskresult/TaskResultRepository.kt index 4118cfed..492b2851 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskresult/TaskResultRepository.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/domain/model/taskresult/TaskResultRepository.kt @@ -20,6 +20,6 @@ import kotlinx.coroutines.flow.Flow import java.util.* interface TaskResultRepository { - suspend fun save(taskResult: TaskResult):TaskResult - fun findByTaskId(id:UUID): Flow -} \ No newline at end of file + suspend fun save(taskResult: TaskResult): TaskResult + fun findByTaskId(id: UUID): Flow +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/external/GrpcExtension.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/external/GrpcExtension.kt index 93159174..601cfe5a 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/external/GrpcExtension.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/external/GrpcExtension.kt @@ -32,4 +32,4 @@ fun UUID.toUUID(): Uuid.UUID = Uuid fun Timestamp.toInstant(): Instant = Instant.ofEpochSecond(seconds, nanos.toLong()) -fun Instant.toTimestamp():Timestamp = Timestamp.newBuilder().setSeconds(this.epochSecond).setNanos(this.nano).build() \ No newline at end of file +fun Instant.toTimestamp(): Timestamp = Timestamp.newBuilder().setSeconds(this.epochSecond).setNanos(this.nano).build() diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/AssignmentTaskService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/AssignmentTaskService.kt index e3f0752c..f0f46d6a 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/AssignmentTaskService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/AssignmentTaskService.kt @@ -16,7 +16,6 @@ package dev.usbharu.owl.broker.interfaces.grpc - import dev.usbharu.owl.broker.external.toTimestamp import dev.usbharu.owl.broker.external.toUUID import dev.usbharu.owl.broker.service.QueuedTaskAssigner @@ -33,7 +32,6 @@ import org.slf4j.LoggerFactory import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext - class AssignmentTaskService( coroutineContext: CoroutineContext = EmptyCoroutineContext, private val queuedTaskAssigner: QueuedTaskAssigner, @@ -42,7 +40,6 @@ class AssignmentTaskService( AssignmentTaskServiceGrpcKt.AssignmentTaskServiceCoroutineImplBase(coroutineContext) { override fun ready(requests: Flow): Flow { - return try { requests .flatMapMerge { @@ -72,4 +69,4 @@ class AssignmentTaskService( companion object { private val logger = LoggerFactory.getLogger(AssignmentTaskService::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/DefinitionTaskService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/DefinitionTaskService.kt index 59afb0d1..a6436405 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/DefinitionTaskService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/DefinitionTaskService.kt @@ -25,17 +25,20 @@ import dev.usbharu.owl.generated.DefinitionTaskServiceGrpcKt.DefinitionTaskServi import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext -class DefinitionTaskService(coroutineContext: CoroutineContext = EmptyCoroutineContext,private val registerTaskService: RegisterTaskService) : +class DefinitionTaskService( + coroutineContext: CoroutineContext = EmptyCoroutineContext, + private val registerTaskService: RegisterTaskService +) : DefinitionTaskServiceCoroutineImplBase(coroutineContext) { override suspend fun register(request: DefinitionTask.TaskDefinition): TaskDefined { registerTaskService.registerTask( TaskDefinition( - request.name, - request.priority, - request.maxRetry, - request.timeoutMilli, - request.propertyDefinitionHash, - request.retryPolicy + name = request.name, + priority = request.priority, + maxRetry = request.maxRetry, + timeoutMilli = request.timeoutMilli, + propertyDefinitionHash = request.propertyDefinitionHash, + retryPolicy = request.retryPolicy ) ) return TaskDefined @@ -50,4 +53,4 @@ class DefinitionTaskService(coroutineContext: CoroutineContext = EmptyCoroutineC registerTaskService.unregisterTask(request.name) return Empty.getDefaultInstance() } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/ProducerService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/ProducerService.kt index d2157a2d..358d6827 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/ProducerService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/ProducerService.kt @@ -24,18 +24,20 @@ import dev.usbharu.owl.generated.ProducerServiceGrpcKt.ProducerServiceCoroutineI import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext - class ProducerService( coroutineContext: CoroutineContext = EmptyCoroutineContext, private val producerService: ProducerService ) : ProducerServiceCoroutineImplBase(coroutineContext) { - override suspend fun registerProducer(request: ProducerOuterClass.Producer): ProducerOuterClass.RegisterProducerResponse { + override suspend fun registerProducer( + request: ProducerOuterClass.Producer + ): ProducerOuterClass.RegisterProducerResponse { val registerProducer = producerService.registerProducer( RegisterProducerRequest( - request.name, request.hostname + request.name, + request.hostname ) ) return ProducerOuterClass.RegisterProducerResponse.newBuilder().setId(registerProducer.toUUID()).build() } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/SubscribeTaskService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/SubscribeTaskService.kt index d8ed8386..a1eadee4 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/SubscribeTaskService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/SubscribeTaskService.kt @@ -34,4 +34,4 @@ class SubscribeTaskService( consumerService.registerConsumer(RegisterConsumerRequest(request.name, request.hostname, request.tasksList)) return Consumer.SubscribeTaskResponse.newBuilder().setId(id.toUUID()).build() } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskPublishService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskPublishService.kt index 8a7bff55..22aff532 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskPublishService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskPublishService.kt @@ -39,13 +39,9 @@ class TaskPublishService( TaskPublishServiceCoroutineImplBase(coroutineContext) { override suspend fun publishTask(request: PublishTaskOuterClass.PublishTask): PublishedTask { - logger.warn("aaaaaaaaaaa") - - return try { - val publishedTask = taskPublishService.publishTask( PublishTask( request.name, @@ -61,7 +57,6 @@ class TaskPublishService( } override suspend fun publishTasks(request: PublishTaskOuterClass.PublishTasks): PublishedTasks { - val tasks = request.propertiesArrayList.map { PublishTask( request.name, @@ -79,4 +74,4 @@ class TaskPublishService( private val logger = LoggerFactory.getLogger(dev.usbharu.owl.broker.interfaces.grpc.TaskPublishService::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultService.kt index 300d3cf5..4c5411e3 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultService.kt @@ -67,4 +67,4 @@ class TaskResultService( companion object { private val logger = LoggerFactory.getLogger(TaskResultService::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultSubscribeService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultSubscribeService.kt index 5855cc6d..6ac87395 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultSubscribeService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/interfaces/grpc/TaskResultSubscribeService.kt @@ -41,16 +41,18 @@ class TaskResultSubscribeService( name = it.name attempt = it.attempt success = it.success - results.addAll(it.results.map { - taskResult { - id = it.taskId.toUUID() - success = it.success - attempt = it.attempt - result.putAll(PropertySerializeUtils.serialize(propertySerializerFactory, it.result)) - message = it.message + results.addAll( + it.results.map { + taskResult { + id = it.taskId.toUUID() + success = it.success + attempt = it.attempt + result.putAll(PropertySerializeUtils.serialize(propertySerializerFactory, it.result)) + message = it.message + } } - }) + ) } } } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/AssignQueuedTaskDecider.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/AssignQueuedTaskDecider.kt index 44dfa36a..e58a56b3 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/AssignQueuedTaskDecider.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/AssignQueuedTaskDecider.kt @@ -42,7 +42,5 @@ class AssignQueuedTaskDeciderImpl( ).take(numberOfConcurrent) ) } - } - -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/ConsumerService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/ConsumerService.kt index 84b21095..3b7da438 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/ConsumerService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/ConsumerService.kt @@ -57,4 +57,4 @@ data class RegisterConsumerRequest( val name: String, val hostname: String, val tasks: List -) \ No newline at end of file +) diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/DefaultPropertySerializerFactory.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/DefaultPropertySerializerFactory.kt index 0eed7b40..84baaf23 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/DefaultPropertySerializerFactory.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/DefaultPropertySerializerFactory.kt @@ -28,4 +28,4 @@ class DefaultPropertySerializerFactory : LongPropertySerializer(), FloatPropertySerializer(), ) - ) \ No newline at end of file + ) diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/ProducerService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/ProducerService.kt index d781ba45..796d6698 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/ProducerService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/ProducerService.kt @@ -26,10 +26,8 @@ interface ProducerService { suspend fun registerProducer(producer: RegisterProducerRequest): UUID } - class ProducerServiceImpl(private val producerRepository: ProducerRepository) : ProducerService { override suspend fun registerProducer(producer: RegisterProducerRequest): UUID { - val id = UUID.randomUUID() val saveProducer = Producer( @@ -54,4 +52,4 @@ class ProducerServiceImpl(private val producerRepository: ProducerRepository) : data class RegisterProducerRequest( val name: String, val hostname: String -) \ No newline at end of file +) diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueueScanner.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueueScanner.kt index 6368c93e..ced1fa20 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueueScanner.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueueScanner.kt @@ -29,19 +29,14 @@ interface QueueScanner { fun startScan(): Flow } - class QueueScannerImpl(private val queueStore: QueueStore) : QueueScanner { - override fun startScan(): Flow { - return flow { - while (currentCoroutineContext().isActive) { - emitAll(scanQueue()) - delay(1000) - } + override fun startScan(): Flow = flow { + while (currentCoroutineContext().isActive) { + emitAll(scanQueue()) + delay(1000) } } - private fun scanQueue(): Flow { - return queueStore.findByQueuedAtBeforeAndIsActiveIsTrue(Instant.now().minusSeconds(10)) - } - -} \ No newline at end of file + private fun scanQueue(): Flow = + queueStore.findByQueuedAtBeforeAndIsActiveIsTrue(Instant.now().minusSeconds(10)) +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueueStore.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueueStore.kt index 990e2b76..2dbb6aaa 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueueStore.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueueStore.kt @@ -32,33 +32,24 @@ interface QueueStore { fun findByQueuedAtBeforeAndIsActiveIsTrue(instant: Instant): Flow } - class QueueStoreImpl(private val queuedTaskRepository: QueuedTaskRepository) : QueueStore { override suspend fun enqueue(queuedTask: QueuedTask) { queuedTaskRepository.save(queuedTask) } - override suspend fun enqueueAll(queuedTaskList: List) { - queuedTaskList.forEach { enqueue(it) } - } + override suspend fun enqueueAll(queuedTaskList: List) = queuedTaskList.forEach { enqueue(it) } override suspend fun dequeue(queuedTask: QueuedTask) { queuedTaskRepository.findByTaskIdAndAssignedConsumerIsNullAndUpdate(queuedTask.task.id, queuedTask) } - override suspend fun dequeueAll(queuedTaskList: List) { - return queuedTaskList.forEach { dequeue(it) } - } + override suspend fun dequeueAll(queuedTaskList: List) = queuedTaskList.forEach { dequeue(it) } override fun findByTaskNameInAndIsActiveIsTrueAndOrderByPriority( tasks: List, limit: Int - ): Flow { - return queuedTaskRepository.findByTaskNameInAndIsActiveIsTrueAndOrderByPriority(tasks, limit) - } + ): Flow = queuedTaskRepository.findByTaskNameInAndIsActiveIsTrueAndOrderByPriority(tasks, limit) - override fun findByQueuedAtBeforeAndIsActiveIsTrue(instant: Instant): Flow { - return queuedTaskRepository.findByQueuedAtBeforeAndIsActiveIsTrue(instant) - } - -} \ No newline at end of file + override fun findByQueuedAtBeforeAndIsActiveIsTrue(instant: Instant): Flow = + queuedTaskRepository.findByQueuedAtBeforeAndIsActiveIsTrue(instant) +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueuedTaskAssigner.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueuedTaskAssigner.kt index 33c95413..caa061af 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueuedTaskAssigner.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/QueuedTaskAssigner.kt @@ -27,7 +27,6 @@ interface QueuedTaskAssigner { fun ready(consumerId: UUID, numberOfConcurrent: Int): Flow } - class QueuedTaskAssignerImpl( private val taskManagementService: TaskManagementService, private val queueStore: QueueStore @@ -49,7 +48,6 @@ class QueuedTaskAssignerImpl( private suspend fun assignTask(queuedTask: QueuedTask, consumerId: UUID): QueuedTask? { return try { - val assignedTaskQueue = queuedTask.copy(assignedConsumer = consumerId, assignedAt = Instant.now(), isActive = false) logger.trace( @@ -78,4 +76,4 @@ class QueuedTaskAssignerImpl( companion object { private val logger = LoggerFactory.getLogger(QueuedTaskAssignerImpl::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/RegisterTaskService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/RegisterTaskService.kt index 58945d42..e9812bce 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/RegisterTaskService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/RegisterTaskService.kt @@ -24,33 +24,34 @@ import org.slf4j.LoggerFactory interface RegisterTaskService { suspend fun registerTask(taskDefinition: TaskDefinition) - suspend fun unregisterTask(name:String) + suspend fun unregisterTask(name: String) } - class RegisterTaskServiceImpl(private val taskDefinitionRepository: TaskDefinitionRepository) : RegisterTaskService { override suspend fun registerTask(taskDefinition: TaskDefinition) { val definedTask = taskDefinitionRepository.findByName(taskDefinition.name) if (definedTask != null) { logger.debug("Task already defined. name: ${taskDefinition.name}") if (taskDefinition.propertyDefinitionHash != definedTask.propertyDefinitionHash) { - throw IncompatibleTaskException("Task ${taskDefinition.name} has already been defined, and the parameters are incompatible.") + throw IncompatibleTaskException( + "Task ${taskDefinition.name} has already been defined, and the parameters are incompatible." + ) } return } taskDefinitionRepository.save(taskDefinition) - logger.info("Register a new task. name: {}",taskDefinition.name) + logger.info("Register a new task. name: {}", taskDefinition.name) } // todo すでにpublish済みのタスクをどうするか決めさせる override suspend fun unregisterTask(name: String) { taskDefinitionRepository.deleteByName(name) - logger.info("Unregister a task. name: {}",name) + logger.info("Unregister a task. name: {}", name) } - companion object{ + companion object { private val logger = LoggerFactory.getLogger(RegisterTaskServiceImpl::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskManagementService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskManagementService.kt index 29133704..c076fecd 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskManagementService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskManagementService.kt @@ -31,7 +31,6 @@ import org.slf4j.LoggerFactory import java.time.Instant import java.util.* - interface TaskManagementService { suspend fun startManagement(coroutineScope: CoroutineScope) @@ -75,13 +74,11 @@ class TaskManagementServiceImpl( } } - override fun findAssignableTask(consumerId: UUID, numberOfConcurrent: Int): Flow { return assignQueuedTaskDecider.findAssignableQueue(consumerId, numberOfConcurrent) } private suspend fun enqueueTask(task: Task): QueuedTask { - val definedTask = taskDefinitionRepository.findByName(task.name) ?: throw TaskNotRegisterException("Task ${task.name} not definition.") @@ -113,7 +110,6 @@ class TaskManagementServiceImpl( queueStore.dequeue(timeoutQueue) - val task = taskRepository.findById(timeoutQueue.task.id) ?: throw RecordNotFoundException("Task not found. id: ${timeoutQueue.task.id}") val copy = task.copy(attempt = timeoutQueue.attempt) @@ -148,12 +144,10 @@ class TaskManagementServiceImpl( taskResult.taskId, task.copy(completedAt = completedAt, attempt = taskResult.attempt) ) - } override fun subscribeResult(producerId: UUID): Flow { return flow { - while (currentCoroutineContext().isActive) { taskRepository .findByPublishProducerIdAndCompletedAtIsNotNull(producerId) @@ -163,7 +157,7 @@ class TaskManagementServiceImpl( TaskResults( it.name, it.id, - results.any { it.success }, + results.any { taskResult -> taskResult.success }, it.attempt, results ) @@ -171,12 +165,10 @@ class TaskManagementServiceImpl( } delay(500) } - } - } companion object { private val logger = LoggerFactory.getLogger(TaskManagementServiceImpl::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskPublishService.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskPublishService.kt index a6604d10..d1dfbe56 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskPublishService.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskPublishService.kt @@ -78,7 +78,6 @@ class TaskPublishServiceImpl( } override suspend fun publishTasks(list: List): List { - val first = list.first() val definition = taskDefinitionRepository.findByName(first.name) @@ -90,14 +89,14 @@ class TaskPublishServiceImpl( val tasks = list.map { Task( - it.name, - UUID.randomUUID(), - first.producerId, - published, - nextRetry, - null, - 0, - it.properties + name = it.name, + id = UUID.randomUUID(), + publishProducerId = first.producerId, + publishedAt = published, + nextRetry = nextRetry, + completedAt = null, + attempt = 0, + properties = it.properties ) } @@ -111,4 +110,4 @@ class TaskPublishServiceImpl( companion object { private val logger = LoggerFactory.getLogger(TaskPublishServiceImpl::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskResults.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskResults.kt index a61dbb0c..e4e48d3c 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskResults.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskResults.kt @@ -20,9 +20,9 @@ import dev.usbharu.owl.broker.domain.model.taskresult.TaskResult import java.util.* data class TaskResults( - val name:String, - val id:UUID, - val success:Boolean, - val attempt:Int, + val name: String, + val id: UUID, + val success: Boolean, + val attempt: Int, val results: List ) diff --git a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskScanner.kt b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskScanner.kt index 5d469533..1966a168 100644 --- a/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskScanner.kt +++ b/owl/owl-broker/src/main/kotlin/dev/usbharu/owl/broker/service/TaskScanner.kt @@ -49,4 +49,4 @@ class TaskScannerImpl(private val taskRepository: TaskRepository) : companion object { private val logger = LoggerFactory.getLogger(TaskScannerImpl::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-common/owl-common-serialize-jackson/src/main/kotlin/dev/usbharu/Main.kt b/owl/owl-common/owl-common-serialize-jackson/src/main/kotlin/dev/usbharu/Main.kt index 64eb428e..511cd2b6 100644 --- a/owl/owl-common/owl-common-serialize-jackson/src/main/kotlin/dev/usbharu/Main.kt +++ b/owl/owl-common/owl-common-serialize-jackson/src/main/kotlin/dev/usbharu/Main.kt @@ -18,4 +18,4 @@ package dev.usbharu fun main() { println("Hello World!") -} \ No newline at end of file +} diff --git a/owl/owl-common/owl-common-serialize-jackson/src/main/kotlin/dev/usbharu/owl/common/property/ObjectPropertyValue.kt b/owl/owl-common/owl-common-serialize-jackson/src/main/kotlin/dev/usbharu/owl/common/property/ObjectPropertyValue.kt index 6583d4f1..52fbb844 100644 --- a/owl/owl-common/owl-common-serialize-jackson/src/main/kotlin/dev/usbharu/owl/common/property/ObjectPropertyValue.kt +++ b/owl/owl-common/owl-common-serialize-jackson/src/main/kotlin/dev/usbharu/owl/common/property/ObjectPropertyValue.kt @@ -45,6 +45,5 @@ class ObjectPropertySerializer(private val objectMapper: ObjectMapper) : Propert Class.forName(string.substringAfter("jackson:").substringBefore(":")) ) ) - } -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/ReflectionUtils.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/ReflectionUtils.kt index f0a6ff90..e72502a6 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/ReflectionUtils.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/ReflectionUtils.kt @@ -23,4 +23,7 @@ val Class<*>.allFields: List superclass.allFields + declaredFields } else { declaredFields.toList() - }.map { it.trySetAccessible();it } \ No newline at end of file + }.map { + it.trySetAccessible() + it + } diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/BooleanPropertyValue.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/BooleanPropertyValue.kt index b595f31c..3774f1a2 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/BooleanPropertyValue.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/BooleanPropertyValue.kt @@ -15,19 +15,12 @@ class BooleanPropertyValue(override val value: Boolean) : PropertyValue * */ class BooleanPropertySerializer : PropertySerializer { - override fun isSupported(propertyValue: PropertyValue<*>): Boolean { - return propertyValue.value is Boolean - } + override fun isSupported(propertyValue: PropertyValue<*>): Boolean = propertyValue.value is Boolean - override fun isSupported(string: String): Boolean { - return string.startsWith("bool:") - } + override fun isSupported(string: String): Boolean = string.startsWith("bool:") - override fun serialize(propertyValue: PropertyValue<*>): String { - return "bool:" + propertyValue.value.toString() - } + override fun serialize(propertyValue: PropertyValue<*>): String = "bool:" + propertyValue.value.toString() - override fun deserialize(string: String): PropertyValue { - return BooleanPropertyValue(string.replace("bool:", "").toBoolean()) - } -} \ No newline at end of file + override fun deserialize(string: String): PropertyValue = + BooleanPropertyValue(string.replace("bool:", "").toBoolean()) +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/CustomPropertySerializerFactory.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/CustomPropertySerializerFactory.kt index 00d7a3f3..e7ea1e53 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/CustomPropertySerializerFactory.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/CustomPropertySerializerFactory.kt @@ -23,12 +23,9 @@ package dev.usbharu.owl.common.property */ open class CustomPropertySerializerFactory(private val propertySerializers: Set>) : PropertySerializerFactory { - override fun factory(propertyValue: PropertyValue): PropertySerializer { - return propertySerializers.firstOrNull { it.isSupported(propertyValue) } as PropertySerializer? + override fun factory(propertyValue: PropertyValue): PropertySerializer = + propertySerializers.firstOrNull { it.isSupported(propertyValue) } as PropertySerializer? ?: throw IllegalArgumentException("PropertySerializer not found: $propertyValue") - } - override fun factory(string: String): PropertySerializer<*> { - return propertySerializers.first { it.isSupported(string) } - } -} \ No newline at end of file + override fun factory(string: String): PropertySerializer<*> = propertySerializers.first { it.isSupported(string) } +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/DoublePropertyValue.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/DoublePropertyValue.kt index c201cbaa..035c2114 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/DoublePropertyValue.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/DoublePropertyValue.kt @@ -15,19 +15,12 @@ class DoublePropertyValue(override val value: Double) : PropertyValue() * */ class DoublePropertySerializer : PropertySerializer { - override fun isSupported(propertyValue: PropertyValue<*>): Boolean { - return propertyValue.value is Double - } + override fun isSupported(propertyValue: PropertyValue<*>): Boolean = propertyValue.value is Double - override fun isSupported(string: String): Boolean { - return string.startsWith("double:") - } + override fun isSupported(string: String): Boolean = string.startsWith("double:") - override fun serialize(propertyValue: PropertyValue<*>): String { - return "double:" + propertyValue.value.toString() - } + override fun serialize(propertyValue: PropertyValue<*>): String = "double:" + propertyValue.value.toString() - override fun deserialize(string: String): PropertyValue { - return DoublePropertyValue(string.replace("double:", "").toDouble()) - } -} \ No newline at end of file + override fun deserialize(string: String): PropertyValue = + DoublePropertyValue(string.replace("double:", "").toDouble()) +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/FloatPropertyValue.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/FloatPropertyValue.kt index 0f18c832..dbb6b68d 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/FloatPropertyValue.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/FloatPropertyValue.kt @@ -26,19 +26,12 @@ class FloatPropertyValue(override val value: Float) : PropertyValue() { * */ class FloatPropertySerializer : PropertySerializer { - override fun isSupported(propertyValue: PropertyValue<*>): Boolean { - return propertyValue.value is Float - } + override fun isSupported(propertyValue: PropertyValue<*>): Boolean = propertyValue.value is Float - override fun isSupported(string: String): Boolean { - return string.startsWith("float:") - } + override fun isSupported(string: String): Boolean = string.startsWith("float:") - override fun serialize(propertyValue: PropertyValue<*>): String { - return "float:" + propertyValue.value.toString() - } + override fun serialize(propertyValue: PropertyValue<*>): String = "float:" + propertyValue.value.toString() - override fun deserialize(string: String): PropertyValue { - return FloatPropertyValue(string.replace("float:", "").toFloat()) - } -} \ No newline at end of file + override fun deserialize(string: String): PropertyValue = + FloatPropertyValue(string.replace("float:", "").toFloat()) +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/IntegerPropertyValue.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/IntegerPropertyValue.kt index 9b49c39c..c593fc24 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/IntegerPropertyValue.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/IntegerPropertyValue.kt @@ -31,19 +31,12 @@ class IntegerPropertyValue(override val value: Int) : PropertyValue() { * */ class IntegerPropertySerializer : PropertySerializer { - override fun isSupported(propertyValue: PropertyValue<*>): Boolean { - return propertyValue.value is Int - } + override fun isSupported(propertyValue: PropertyValue<*>): Boolean = propertyValue.value is Int - override fun isSupported(string: String): Boolean { - return string.startsWith("int32:") - } + override fun isSupported(string: String): Boolean = string.startsWith("int32:") - override fun serialize(propertyValue: PropertyValue<*>): String { - return "int32:" + propertyValue.value.toString() - } + override fun serialize(propertyValue: PropertyValue<*>): String = "int32:" + propertyValue.value.toString() - override fun deserialize(string: String): PropertyValue { - return IntegerPropertyValue(string.replace("int32:", "").toInt()) - } -} \ No newline at end of file + override fun deserialize(string: String): PropertyValue = + IntegerPropertyValue(string.replace("int32:", "").toInt()) +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/LongPropertyValue.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/LongPropertyValue.kt index 660b0b69..ebbb80df 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/LongPropertyValue.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/LongPropertyValue.kt @@ -27,19 +27,12 @@ class LongPropertyValue(override val value: Long) : PropertyValue() { * */ class LongPropertySerializer : PropertySerializer { - override fun isSupported(propertyValue: PropertyValue<*>): Boolean { - return propertyValue.value is Long - } + override fun isSupported(propertyValue: PropertyValue<*>): Boolean = propertyValue.value is Long - override fun isSupported(string: String): Boolean { - return string.startsWith("int64:") - } + override fun isSupported(string: String): Boolean = string.startsWith("int64:") - override fun serialize(propertyValue: PropertyValue<*>): String { - return "int64:" + propertyValue.value.toString() - } + override fun serialize(propertyValue: PropertyValue<*>): String = "int64:" + propertyValue.value.toString() - override fun deserialize(string: String): PropertyValue { - return LongPropertyValue(string.replace("int64:", "").toLong()) - } -} \ No newline at end of file + override fun deserialize(string: String): PropertyValue = + LongPropertyValue(string.replace("int64:", "").toLong()) +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializeException.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializeException.kt index 4acc597d..b1d29663 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializeException.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializeException.kt @@ -27,4 +27,4 @@ class PropertySerializeException : RuntimeException { enableSuppression, writableStackTrace ) -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializeUtils.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializeUtils.kt index 817f3d24..9ae57a50 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializeUtils.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializeUtils.kt @@ -59,4 +59,4 @@ object PropertySerializeUtils { } }.toMap() } -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializer.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializer.kt index 950bd9f4..62e1ceff 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializer.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializer.kt @@ -53,4 +53,4 @@ interface PropertySerializer { * @return デシリアライズされた[PropertyValue] */ fun deserialize(string: String): PropertyValue -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializerFactory.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializerFactory.kt index 9983d6cf..22ac4466 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializerFactory.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertySerializerFactory.kt @@ -37,4 +37,4 @@ interface PropertySerializerFactory { * @return 作成されたシリアライザー */ fun factory(string: String): PropertySerializer<*> -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertyType.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertyType.kt index 4259c62f..047e7655 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertyType.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertyType.kt @@ -38,4 +38,4 @@ enum class PropertyType { * */ binary -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertyValue.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertyValue.kt index d04ca229..cbedabf3 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertyValue.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/PropertyValue.kt @@ -31,9 +31,5 @@ abstract class PropertyValue { * プロパティの型 */ abstract val type: PropertyType - override fun toString(): String { - return "PropertyValue(value=$value, type=$type)" - } - - -} \ No newline at end of file + override fun toString(): String = "PropertyValue(value=$value, type=$type)" +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/StringPropertyValue.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/StringPropertyValue.kt index 5b4cbaa1..edd5c393 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/StringPropertyValue.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/property/StringPropertyValue.kt @@ -15,19 +15,11 @@ class StringPropertyValue(override val value: String) : PropertyValue() * */ class StringPropertyValueSerializer : PropertySerializer { - override fun isSupported(propertyValue: PropertyValue<*>): Boolean { - return propertyValue.value is String - } + override fun isSupported(propertyValue: PropertyValue<*>): Boolean = propertyValue.value is String - override fun isSupported(string: String): Boolean { - return string.startsWith("str:") - } + override fun isSupported(string: String): Boolean = string.startsWith("str:") - override fun serialize(propertyValue: PropertyValue<*>): String { - return "str:" + propertyValue.value - } + override fun serialize(propertyValue: PropertyValue<*>): String = "str:" + propertyValue.value - override fun deserialize(string: String): PropertyValue { - return StringPropertyValue(string.replace("str:", "")) - } -} \ No newline at end of file + override fun deserialize(string: String): PropertyValue = StringPropertyValue(string.replace("str:", "")) +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/ExponentialRetryPolicy.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/ExponentialRetryPolicy.kt index b34cacf5..78918a04 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/ExponentialRetryPolicy.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/ExponentialRetryPolicy.kt @@ -13,5 +13,4 @@ import kotlin.math.roundToLong class ExponentialRetryPolicy(private val firstRetrySeconds: Int = 30) : RetryPolicy { override fun nextRetry(now: Instant, attempt: Int): Instant = now.plusSeconds(firstRetrySeconds.times((2.0).pow(attempt).roundToLong()) - firstRetrySeconds) - -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicy.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicy.kt index da6e4ec0..755dd45e 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicy.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicy.kt @@ -33,4 +33,4 @@ interface RetryPolicy { * @return 次のリトライ時刻 */ fun nextRetry(now: Instant, attempt: Int): Instant -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicyFactory.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicyFactory.kt index 6948e7bf..75590e84 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicyFactory.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicyFactory.kt @@ -16,7 +16,6 @@ package dev.usbharu.owl.common.retry - import org.slf4j.LoggerFactory interface RetryPolicyFactory { @@ -24,9 +23,7 @@ interface RetryPolicyFactory { } class DefaultRetryPolicyFactory(private val map: Map) : RetryPolicyFactory { - override fun factory(name: String): RetryPolicy { - return map[name] ?: throwException(name) - } + override fun factory(name: String): RetryPolicy = map[name] ?: throwException(name) private fun throwException(name: String): Nothing { logger.warn("RetryPolicy not found. name: {}", name) @@ -36,4 +33,4 @@ class DefaultRetryPolicyFactory(private val map: Map) : Ret companion object { private val logger = LoggerFactory.getLogger(RetryPolicyFactory::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicyNotFoundException.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicyNotFoundException.kt index dba37f35..d16ed33f 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicyNotFoundException.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/retry/RetryPolicyNotFoundException.kt @@ -27,4 +27,4 @@ class RetryPolicyNotFoundException : RuntimeException { enableSuppression, writableStackTrace ) -} \ No newline at end of file +} diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/PropertyDefinition.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/PropertyDefinition.kt index cbc96b0b..ed1a2b3f 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/PropertyDefinition.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/PropertyDefinition.kt @@ -36,6 +36,4 @@ class PropertyDefinition(val map: Map) : Map( val task: T, val id: UUID, val published: Instant -) \ No newline at end of file +) diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/Task.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/Task.kt index f29d5d2d..e83a2807 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/Task.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/Task.kt @@ -20,4 +20,4 @@ package dev.usbharu.owl.common.task * タスク * */ -open class Task \ No newline at end of file +open class Task diff --git a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/TaskDefinition.kt b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/TaskDefinition.kt index 5cced498..57b04aed 100644 --- a/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/TaskDefinition.kt +++ b/owl/owl-common/src/main/kotlin/dev/usbharu/owl/common/task/TaskDefinition.kt @@ -107,7 +107,6 @@ interface TaskDefinition { * @return デシリアライズされたタスク */ fun deserialize(value: Map>): T { - val task = try { type.getDeclaredConstructor().newInstance() } catch (e: Exception) { @@ -127,4 +126,4 @@ interface TaskDefinition { return task } -} \ No newline at end of file +} diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/AbstractTaskRunner.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/AbstractTaskRunner.kt index e1a5125e..18bbff55 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/AbstractTaskRunner.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/AbstractTaskRunner.kt @@ -29,5 +29,4 @@ abstract class AbstractTaskRunner>(private val t } abstract suspend fun typedRun(typedParam: T, taskRequest: TaskRequest): TaskResult - -} \ No newline at end of file +} diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Consumer.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Consumer.kt index ee925335..0069465d 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Consumer.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Consumer.kt @@ -66,11 +66,13 @@ class Consumer( suspend fun init(name: String, hostname: String) { logger.info("Initialize Consumer name: {} hostname: {}", name, hostname) logger.debug("Registered Tasks: {}", runnerMap.keys) - consumerId = subscribeTaskStub.subscribeTask(subscribeTaskRequest { - this.name = name - this.hostname = hostname - this.tasks.addAll(runnerMap.keys) - }).id + consumerId = subscribeTaskStub.subscribeTask( + subscribeTaskRequest { + this.name = name + this.hostname = hostname + this.tasks.addAll(runnerMap.keys) + } + ).id logger.info("Success initialize consumer. ConsumerID: {}", consumerId) } @@ -84,78 +86,92 @@ class Consumer( while (isActive) { try { taskResultStub - .tasKResult(flow { - assignmentTaskStub - .ready(flow { - requestTask() - }).onEach { - logger.info("Start Task name: {} id: {}", it.name, it.id) - processing.update { it + 1 } + .tasKResult( + flow { + assignmentTaskStub + .ready( + flow { + requestTask() + } + ).onEach { + logger.info("Start Task name: {} id: {}", it.name, it.id) + processing.update { it + 1 } - try { - val taskResult = runnerMap.getValue(it.name).run( - TaskRequest( + try { + val taskResult = runnerMap.getValue(it.name).run( + TaskRequest( + it.name, + java.util.UUID( + it.id.mostSignificantUuidBits, + it.id.leastSignificantUuidBits + ), + it.attempt, + Instant.ofEpochSecond( + it.queuedAt.seconds, + it.queuedAt.nanos.toLong() + ), + PropertySerializeUtils.deserialize( + propertySerializerFactory, + it.propertiesMap + ) + ) + ) + + emit( + taskResult { + this.success = taskResult.success + this.attempt = it.attempt + this.id = it.id + this.result.putAll( + PropertySerializeUtils.serialize( + propertySerializerFactory, + taskResult.result + ) + ) + this.message = taskResult.message + } + ) + logger.info( + "Success execute task. name: {} success: {}", it.name, - java.util.UUID( - it.id.mostSignificantUuidBits, - it.id.leastSignificantUuidBits - ), - it.attempt, - Instant.ofEpochSecond(it.queuedAt.seconds, it.queuedAt.nanos.toLong()), - PropertySerializeUtils.deserialize( - propertySerializerFactory, - it.propertiesMap - ) + taskResult.success ) - ) - - emit(taskResult { - this.success = taskResult.success - this.attempt = it.attempt - this.id = it.id - this.result.putAll( - PropertySerializeUtils.serialize( - propertySerializerFactory, taskResult.result - ) + logger.debug("TRACE RESULT {}", taskResult) + } catch (e: CancellationException) { + logger.warn("Cancelled execute task.", e) + emit( + taskResult { + this.success = false + this.attempt = it.attempt + this.id = it.id + this.message = e.localizedMessage + } ) - this.message = taskResult.message - }) - logger.info( - "Success execute task. name: {} success: {}", - it.name, - taskResult.success - ) - logger.debug("TRACE RESULT {}", taskResult) - } catch (e: CancellationException) { - logger.warn("Cancelled execute task.", e) - emit(taskResult { - this.success = false - this.attempt = it.attempt - this.id = it.id - this.message = e.localizedMessage - }) - throw e - } catch (e: Exception) { - logger.warn("Failed execute task. name: {} id: {}", it.name, it.id, e) - emit(taskResult { - this.success = false - this.attempt = it.attempt - this.id = it.id - this.message = e.localizedMessage - }) - } finally { - logger.debug(" Task name: {} id: {}", it.name, it.id) - processing.update { it - 1 } - concurrent.update { - if (it < 64) { - it + 1 - } else { - 64 + throw e + } catch (e: Exception) { + logger.warn("Failed execute task. name: {} id: {}", it.name, it.id, e) + emit( + taskResult { + this.success = false + this.attempt = it.attempt + this.id = it.id + this.message = e.localizedMessage + } + ) + } finally { + logger.debug(" Task name: {} id: {}", it.name, it.id) + processing.update { it - 1 } + concurrent.update { + if (it < 64) { + it + 1 + } else { + 64 + } } } - } - }.flowOn(Dispatchers.Default).collect() - }) + }.flowOn(Dispatchers.Default).collect() + } + ) } catch (e: CancellationException) { throw e } catch (e: Exception) { @@ -171,14 +187,15 @@ class Consumer( while (coroutineScope.isActive) { val andSet = concurrent.getAndUpdate { 0 } - if (andSet != 0) { logger.debug("Request {} tasks.", andSet) try { - emit(readyRequest { - this.consumerId = this@Consumer.consumerId - this.numberOfConcurrent = andSet - }) + emit( + readyRequest { + this.consumerId = this@Consumer.consumerId + this.numberOfConcurrent = andSet + } + ) } catch (e: CancellationException) { throw e } catch (e: Exception) { @@ -206,4 +223,4 @@ class Consumer( companion object { private val logger = LoggerFactory.getLogger(Consumer::class.java) } -} \ No newline at end of file +} diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Main.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Main.kt index 31fba291..9ba808b1 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Main.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/Main.kt @@ -25,5 +25,4 @@ fun main() { standaloneConsumer.init() standaloneConsumer.start() } - -} \ No newline at end of file +} diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/ServiceLoaderTaskRunnerLoader.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/ServiceLoaderTaskRunnerLoader.kt index a34fc37b..1a639b81 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/ServiceLoaderTaskRunnerLoader.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/ServiceLoaderTaskRunnerLoader.kt @@ -26,4 +26,4 @@ class ServiceLoaderTaskRunnerLoader : TaskRunnerLoader { override fun load(): Map { return taskRunnerMap } -} \ No newline at end of file +} diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumer.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumer.kt index a9b42635..215d9ca1 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumer.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumer.kt @@ -90,9 +90,11 @@ class StandaloneConsumer( */ suspend fun start() { consumer.start() - Runtime.getRuntime().addShutdownHook(Thread { - consumer.stop() - }) + Runtime.getRuntime().addShutdownHook( + Thread { + consumer.stop() + } + ) } /** @@ -102,5 +104,4 @@ class StandaloneConsumer( fun stop() { consumer.stop() } - -} \ No newline at end of file +} diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumerConfigLoader.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumerConfigLoader.kt index d11bda43..b4c65667 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumerConfigLoader.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/StandaloneConsumerConfigLoader.kt @@ -43,4 +43,4 @@ object StandaloneConsumerConfigLoader { return StandaloneConsumerConfig(address, port, name, hostname, concurrency) } -} \ No newline at end of file +} diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRequest.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRequest.kt index 006856f2..fa735fc9 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRequest.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRequest.kt @@ -30,9 +30,9 @@ import java.util.* * @property properties タスクに渡されたパラメータ */ data class TaskRequest( - val name:String, - val id:UUID, - val attempt:Int, + val name: String, + val id: UUID, + val attempt: Int, val queuedAt: Instant, - val properties:Map> + val properties: Map> ) diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskResult.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskResult.kt index 07d4bd9f..d6b6bf78 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskResult.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskResult.kt @@ -35,4 +35,4 @@ data class TaskResult( return TaskResult(true, result, "") } } -} \ No newline at end of file +} diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRunner.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRunner.kt index 613b0166..234a7a68 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRunner.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRunner.kt @@ -33,4 +33,4 @@ interface TaskRunner { * @return タスク実行結果 */ suspend fun run(taskRequest: TaskRequest): TaskResult -} \ No newline at end of file +} diff --git a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRunnerLoader.kt b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRunnerLoader.kt index 2581e5de..5b9f211b 100644 --- a/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRunnerLoader.kt +++ b/owl/owl-consumer/src/main/kotlin/dev/usbharu/owl/consumer/TaskRunnerLoader.kt @@ -18,4 +18,4 @@ package dev.usbharu.owl.consumer interface TaskRunnerLoader { fun load(): Map -} \ No newline at end of file +} diff --git a/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerBuilder.kt b/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerBuilder.kt index 0678266e..f0b288cb 100644 --- a/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerBuilder.kt +++ b/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerBuilder.kt @@ -43,4 +43,4 @@ interface OwlProducerBuilder

{ * @return 作成された[OwlProducer] */ fun build(): P -} \ No newline at end of file +} diff --git a/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerBuilderConfig.kt b/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerBuilderConfig.kt index efedddf0..b0d11048 100644 --- a/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerBuilderConfig.kt +++ b/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerBuilderConfig.kt @@ -31,4 +31,4 @@ fun

, C : OwlProducerConfig> OWL( ): P { owlProducerBuilder.apply(owlProducerBuilder.config().apply { configBlock() }) return owlProducerBuilder.build() -} \ No newline at end of file +} diff --git a/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerConfig.kt b/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerConfig.kt index 9334b0fd..82618a45 100644 --- a/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerConfig.kt +++ b/owl/owl-producer/owl-producer-api/src/main/kotlin/dev/usbharu/owl/producer/api/OwlProducerConfig.kt @@ -20,4 +20,4 @@ package dev.usbharu.owl.producer.api * [OwlProducer]の構成 * */ -interface OwlProducerConfig \ No newline at end of file +interface OwlProducerConfig diff --git a/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducer.kt b/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducer.kt index 065eb28e..62bbb7b1 100644 --- a/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducer.kt +++ b/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducer.kt @@ -36,10 +36,12 @@ class DefaultOwlProducer(private val defaultOwlProducerConfig: DefaultOwlProduce override suspend fun start() { producerServiceCoroutineStub = ProducerServiceGrpcKt.ProducerServiceCoroutineStub(defaultOwlProducerConfig.channel) - producerId = producerServiceCoroutineStub.registerProducer(producer { - this.name = defaultOwlProducerConfig.name - this.hostname = defaultOwlProducerConfig.hostname - }).id + producerId = producerServiceCoroutineStub.registerProducer( + producer { + this.name = defaultOwlProducerConfig.name + this.hostname = defaultOwlProducerConfig.hostname + } + ).id defineTaskServiceCoroutineStub = DefinitionTaskServiceGrpcKt.DefinitionTaskServiceCoroutineStub(defaultOwlProducerConfig.channel) @@ -48,17 +50,18 @@ class DefaultOwlProducer(private val defaultOwlProducerConfig: DefaultOwlProduce TaskPublishServiceGrpcKt.TaskPublishServiceCoroutineStub(defaultOwlProducerConfig.channel) } - override suspend fun registerTask(taskDefinition: TaskDefinition) { - defineTaskServiceCoroutineStub.register(taskDefinition { - this.producerId = this@DefaultOwlProducer.producerId - this.name = taskDefinition.name - this.maxRetry = taskDefinition.maxRetry - this.priority = taskDefinition.priority - this.retryPolicy = taskDefinition.retryPolicy - this.timeoutMilli = taskDefinition.timeoutMilli - this.propertyDefinitionHash = taskDefinition.propertyDefinition.hash() - }) + defineTaskServiceCoroutineStub.register( + taskDefinition { + this.producerId = this@DefaultOwlProducer.producerId + this.name = taskDefinition.name + this.maxRetry = taskDefinition.maxRetry + this.priority = taskDefinition.priority + this.retryPolicy = taskDefinition.retryPolicy + this.timeoutMilli = taskDefinition.timeoutMilli + this.propertyDefinitionHash = taskDefinition.propertyDefinition.hash() + } + ) } override suspend fun publishTask(task: T): PublishedTask { @@ -91,4 +94,4 @@ class DefaultOwlProducer(private val defaultOwlProducerConfig: DefaultOwlProduce override suspend fun stop() { defaultOwlProducerConfig.channel.shutdownNow() } -} \ No newline at end of file +} diff --git a/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducerBuilder.kt b/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducerBuilder.kt index 4e45e9f4..cc7f6787 100644 --- a/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducerBuilder.kt +++ b/owl/owl-producer/owl-producer-default/src/main/kotlin/dev/usbharu/owl/producer/defaultimpl/DefaultOwlProducerBuilder.kt @@ -44,4 +44,4 @@ class DefaultOwlProducerBuilder : OwlProducerBuilder publishTask(task: T): PublishedTask { - val taskDefinition = taskMap.getValue(task::class.java) as TaskDefinition val publishTask = application.get().publishTask( @@ -117,4 +116,4 @@ class EmbeddedOwlProducer( override suspend fun stop() { brokerApplication.stop() } -} \ No newline at end of file +} diff --git a/owl/owl-producer/owl-producer-embedded/src/main/kotlin/dev/usbharu/owl/producer/embedded/EmbeddedOwlProducerBuilder.kt b/owl/owl-producer/owl-producer-embedded/src/main/kotlin/dev/usbharu/owl/producer/embedded/EmbeddedOwlProducerBuilder.kt index e92b6fc9..37b75808 100644 --- a/owl/owl-producer/owl-producer-embedded/src/main/kotlin/dev/usbharu/owl/producer/embedded/EmbeddedOwlProducerBuilder.kt +++ b/owl/owl-producer/owl-producer-embedded/src/main/kotlin/dev/usbharu/owl/producer/embedded/EmbeddedOwlProducerBuilder.kt @@ -46,7 +46,6 @@ class EmbeddedOwlProducerBuilder : OwlProducerBuilder Date: Tue, 17 Sep 2024 22:07:40 +0900 Subject: [PATCH 34/56] fix: typo --- .github/workflows/pull-request-merge-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index aa68bd97..31699d8a 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -27,7 +27,7 @@ jobs: core: ${{ steps.filter.outputs.core }} mastodon: ${{ steps.filter.outputs.mastodon }} activitypub: ${{ steps.filter.outputs.ap }} - owl: $${{ steps.filter.outputs.owl }} + owl: ${{ steps.filter.outputs.owl }} steps: - name: Checkout uses: actions/checkout@v4 From 0b1fe6eefc173cfccb1ecdc9d43899ddb14ec804 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 22:20:10 +0900 Subject: [PATCH 35/56] =?UTF-8?q?chore:=20=E3=81=AA=E3=81=9C=E3=81=8BGradl?= =?UTF-8?q?e=E3=81=8C=E5=8B=9D=E6=89=8B=E3=81=AB=E9=81=95=E3=81=86?= =?UTF-8?q?=E3=83=97=E3=83=AD=E3=82=B8=E3=82=A7=E3=82=AF=E3=83=88=E3=82=92?= =?UTF-8?q?=E9=96=8B=E3=81=84=E3=81=A6=E3=81=97=E3=81=BE=E3=81=86=E3=81=AE?= =?UTF-8?q?=E3=81=A7=E5=BC=B7=E5=88=B6=E7=9A=84=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 31699d8a..aad63695 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -166,7 +166,8 @@ jobs: gradle-home-cache-cleanup: true - name: Build - run: ./owl/gradlew :owl:classes --no-daemon + working-directory: owl + run: ./gradlew :classes --no-daemon hideout-core-unit-test: needs: From 35eded28e5d2fb63d200204fbb6f6ba4e837ed29 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 22:36:34 +0900 Subject: [PATCH 36/56] =?UTF-8?q?chore:=20=E3=81=AA=E3=81=9C=E3=81=8BGradl?= =?UTF-8?q?e=E3=81=8C=E5=8B=9D=E6=89=8B=E3=81=AB=E9=81=95=E3=81=86?= =?UTF-8?q?=E3=83=97=E3=83=AD=E3=82=B8=E3=82=A7=E3=82=AF=E3=83=88=E3=82=92?= =?UTF-8?q?=E9=96=8B=E3=81=84=E3=81=A6=E3=81=97=E3=81=BE=E3=81=86=E3=81=AE?= =?UTF-8?q?=E3=81=A7=E5=BC=B7=E5=88=B6=E7=9A=84=E3=81=AB=E5=A4=89=E6=9B=B4?= =?UTF-8?q?2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index aad63695..37fa1894 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -312,7 +312,8 @@ jobs: gradle-home-cache-cleanup: true - name: Unit Test - run: ./owl/gradlew :owl:koverXmlReport + working-directory: owl + run: ./gradlew :koverXmlReport - name: JUnit Test Report uses: mikepenz/action-junit-report@v4 From ec0934a41192429fcb65548095029df04ee48ef7 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 22:46:38 +0900 Subject: [PATCH 37/56] =?UTF-8?q?chore:=20activitypub=E3=81=A7detekt?= =?UTF-8?q?=E3=81=8C=E5=8B=95=E3=81=8F=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 3 ++- hideout-activitypub/build.gradle.kts | 9 +++++++++ hideout-activitypub/src/main/kotlin/Main.kt | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index 37fa1894..f8408269 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -391,7 +391,8 @@ jobs: - name: owl Lint if: always() - run: ./owl/gradlew :owl:detektMain + working-directory: owl + run: ./gradlew :detektMain - name: Auto Commit if: ${{ always() }} diff --git a/hideout-activitypub/build.gradle.kts b/hideout-activitypub/build.gradle.kts index 8c14e9a6..219cda28 100644 --- a/hideout-activitypub/build.gradle.kts +++ b/hideout-activitypub/build.gradle.kts @@ -15,6 +15,7 @@ repositories { dependencies { testImplementation(kotlin("test")) + detektPlugins(libs.detekt.formatting) } tasks.test { @@ -66,6 +67,14 @@ project.gradle.taskGraph.whenReady { } } +detekt { + parallel = true + config.setFrom(files("../detekt.yml")) + buildUponDefaultConfig = true + basePath = "${rootDir.absolutePath}/src/main/kotlin" + autoCorrect = true +} + kover { currentProject { sources { diff --git a/hideout-activitypub/src/main/kotlin/Main.kt b/hideout-activitypub/src/main/kotlin/Main.kt index 27f6ee1a..e4395ff8 100644 --- a/hideout-activitypub/src/main/kotlin/Main.kt +++ b/hideout-activitypub/src/main/kotlin/Main.kt @@ -2,4 +2,4 @@ package dev.usbharu fun main() { println("Hello World!") -} \ No newline at end of file +} From 0fe96360a907f5d40307374947b2f96a65431d3f Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 22:48:04 +0900 Subject: [PATCH 38/56] =?UTF-8?q?chore:=20gradlew=E3=81=AE=E3=83=91?= =?UTF-8?q?=E3=83=BC=E3=83=9F=E3=83=83=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92?= =?UTF-8?q?=E8=A8=AD=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hideout-activitypub/gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 hideout-activitypub/gradlew diff --git a/hideout-activitypub/gradlew b/hideout-activitypub/gradlew old mode 100644 new mode 100755 From 30b58c1e149f0b57531df3a456685e561f0b2f3f Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 22:56:31 +0900 Subject: [PATCH 39/56] =?UTF-8?q?chore:=20gradle=E3=81=8C=E3=81=AA?= =?UTF-8?q?=E3=81=9C=E3=81=8B=E3=82=AD=E3=83=A3=E3=83=83=E3=82=B7=E3=83=A5?= =?UTF-8?q?=E3=82=92=E4=BD=BF=E3=81=A3=E3=81=A6=E3=81=97=E3=81=BE=E3=81=86?= =?UTF-8?q?=E3=81=AE=E3=81=A7=E5=BC=B7=E5=88=B6=E7=9A=84=E3=81=ABk?= =?UTF-8?q?=E7=A0=B4=E6=A3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 2 +- owl/build.gradle.kts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index f8408269..b57fba99 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -313,7 +313,7 @@ jobs: - name: Unit Test working-directory: owl - run: ./gradlew :koverXmlReport + run: ./gradlew :koverXmlReport --rerun-task - name: JUnit Test Report uses: mikepenz/action-junit-report@v4 diff --git a/owl/build.gradle.kts b/owl/build.gradle.kts index 5443b6b6..adff1087 100644 --- a/owl/build.gradle.kts +++ b/owl/build.gradle.kts @@ -55,7 +55,7 @@ subprojects { project.gradle.taskGraph.whenReady { if (this.hasTask(":koverGenerateArtifact")) { - val task = this.allTasks.find { println(it.name);it.name == "test" } + val task = this.allTasks.find { it.name == "test" } val verificationTask = task as VerificationTask verificationTask.ignoreFailures = true } @@ -152,8 +152,8 @@ kover { } total { xml { - title = "Hideout Core" - xmlFile = file("$buildDir/reports/kover/hideout-core.xml") + title = "Owl" + xmlFile = file("$buildDir/reports/kover/owl.xml") } filters { excludes { From 80918e1c2e40baba0932f540759fbe0f1d18b8f3 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 17 Sep 2024 22:59:13 +0900 Subject: [PATCH 40/56] =?UTF-8?q?chore:=20typo=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pull-request-merge-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index b57fba99..eafe81c6 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -313,7 +313,7 @@ jobs: - name: Unit Test working-directory: owl - run: ./gradlew :koverXmlReport --rerun-task + run: ./gradlew :koverXmlReport --rerun-tasks - name: JUnit Test Report uses: mikepenz/action-junit-report@v4 From 350f17c0b1b6247b675d86500897532767027290 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 02:57:12 +0000 Subject: [PATCH 41/56] chore(deps): update dorny/paths-filter action to v3 --- .github/workflows/pull-request-merge-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index eafe81c6..7e2e55ac 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -35,7 +35,7 @@ jobs: token: ${{ secrets.PAT }} - name: Check Changes - uses: dorny/paths-filter@v2 + uses: dorny/paths-filter@v3 id: filter with: filters: | From 6d233a1d39ee1c0bd06afcf26384bcfdbf0977a0 Mon Sep 17 00:00:00 2001 From: usbharu Date: Wed, 18 Sep 2024 12:49:07 +0900 Subject: [PATCH 42/56] wip --- .../model/followtimeline/FollowTimeline.kt | 22 --- .../FollowTimelineRepository.kt | 22 --- .../domain/model/relationship/Relationship.kt | 2 +- .../model/relationship/RelationshipTest.kt | 140 ++++++++++++++++++ 4 files changed, 141 insertions(+), 45 deletions(-) delete mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/followtimeline/FollowTimeline.kt delete mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/followtimeline/FollowTimelineRepository.kt create mode 100644 hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipTest.kt diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/followtimeline/FollowTimeline.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/followtimeline/FollowTimeline.kt deleted file mode 100644 index 463e4c32..00000000 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/followtimeline/FollowTimeline.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2024 usbharu - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.usbharu.hideout.core.domain.model.followtimeline - -import dev.usbharu.hideout.core.domain.model.timeline.TimelineId -import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId - -class FollowTimeline(val userDetailId: UserDetailId, val timelineId: TimelineId) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/followtimeline/FollowTimelineRepository.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/followtimeline/FollowTimelineRepository.kt deleted file mode 100644 index 92273f70..00000000 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/followtimeline/FollowTimelineRepository.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2024 usbharu - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dev.usbharu.hideout.core.domain.model.followtimeline - -interface FollowTimelineRepository { - suspend fun save(followTimeline: FollowTimeline): FollowTimeline - suspend fun delete(followTimeline: FollowTimeline) -} diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt index f1f48851..87bccaea 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt @@ -53,7 +53,7 @@ class Relationship( } fun block() { - require(following.not()) + unfollow() blocking = true addDomainEvent(RelationshipEventFactory(this).createEvent(RelationshipEvent.BLOCK)) } diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipTest.kt new file mode 100644 index 00000000..7a299558 --- /dev/null +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipTest.kt @@ -0,0 +1,140 @@ +package dev.usbharu.hideout.core.domain.model.relationship + +import dev.usbharu.hideout.core.domain.event.relationship.RelationshipEvent +import dev.usbharu.hideout.core.domain.model.actor.ActorId +import org.junit.jupiter.api.Test +import utils.AssertDomainEvent.assertContainsEvent +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class RelationshipTest { + @Test + fun unfollow_フォローとフォローリクエストが取り消されUNFOLLOWとUNFOLLOW_REQUESTが発生する() { + val relationship = Relationship( + actorId = ActorId(1), + targetActorId = ActorId(2), + following = true, + blocking = false, + muting = false, + followRequesting = false, + mutingFollowRequest = false + ) + + relationship.unfollow() + + assertFalse(relationship.following) + assertFalse(relationship.followRequesting) + assertContainsEvent(relationship, RelationshipEvent.UNFOLLOW.eventName) + assertContainsEvent(relationship, RelationshipEvent.UNFOLLOW_REQUEST.eventName) + } + + @Test + fun block_unfollowされblockが発生する() { + val relationship = Relationship( + actorId = ActorId(1), + targetActorId = ActorId(2), + following = true, + blocking = false, + muting = false, + followRequesting = false, + mutingFollowRequest = false + ) + + relationship.block() + + assertTrue(relationship.blocking) + assertContainsEvent(relationship, RelationshipEvent.BLOCK.eventName) + } + + @Test + fun mute_MUTEが発生する() { + val relationship = Relationship( + actorId = ActorId(1), + targetActorId = ActorId(2), + following = true, + blocking = false, + muting = false, + followRequesting = false, + mutingFollowRequest = false + ) + + relationship.mute() + + assertTrue(relationship.muting) + assertContainsEvent(relationship, RelationshipEvent.MUTE.eventName) + } + + @Test + fun unmute_UNMUTEが発生する() { + val relationship = Relationship( + actorId = ActorId(1), + targetActorId = ActorId(2), + following = true, + blocking = false, + muting = true, + followRequesting = false, + mutingFollowRequest = true + ) + + relationship.unmute() + + assertFalse(relationship.muting) + assertContainsEvent(relationship, RelationshipEvent.UNMUTE.eventName) + } + + @Test + fun muteFollowRequest_muteFollowiRequestがtrueになる() { + val relationship = Relationship( + actorId = ActorId(1), + targetActorId = ActorId(2), + following = true, + blocking = false, + muting = false, + followRequesting = true, + mutingFollowRequest = false + ) + + relationship.muteFollowRequest() + + assertTrue(relationship.mutingFollowRequest) + } + + @Test + fun unmuteFollowRequest_muteFollowiRequestがfalseになる() { + val relationship = Relationship( + actorId = ActorId(1), + targetActorId = ActorId(2), + following = true, + blocking = false, + muting = false, + followRequesting = true, + mutingFollowRequest = true + ) + + relationship.unmuteFollowRequest() + + assertFalse(relationship.mutingFollowRequest) + } + + @Test + fun followRequest_followRequestingがtrueになりFOLLOW_REQUESTが発生する() { + + } + + @Test + fun followRequest_ブロックしている場合はフォローリクエストを送れない() { + + } + + @Test + fun unfollowRequest_followRequestingがfalseになりUNFOLLOW_REQUESTが発生する() { + + } + + @Test + fun acceptFollowRequest_followingがtrueにfollowRequestingがfalseになりaccept_followが発生する() { + + } + + +} \ No newline at end of file From 1020fe2adfd68b8e0afd7e7f6f711db4c2a676ea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 18 Sep 2024 07:16:01 +0000 Subject: [PATCH 43/56] chore(deps): update madrapps/jacoco-report action to v1.7.1 --- .github/workflows/pull-request-merge-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull-request-merge-check.yml b/.github/workflows/pull-request-merge-check.yml index eafe81c6..dc73e515 100644 --- a/.github/workflows/pull-request-merge-check.yml +++ b/.github/workflows/pull-request-merge-check.yml @@ -343,7 +343,7 @@ jobs: path: 'hideout-core/build/reports/kover' - name: Report Coverage - uses: madrapps/jacoco-report@v1.7.0 + uses: madrapps/jacoco-report@v1.7.1 with: paths: | ${{ github.workspace }}/hideout-core/build/reports/kover/hideout-core.xml/hideout-core.xml, From 9677b11f5c7dce83572126b421c94119f11d8b6c Mon Sep 17 00:00:00 2001 From: usbharu Date: Wed, 18 Sep 2024 23:26:03 +0900 Subject: [PATCH 44/56] =?UTF-8?q?feat:=20=E3=83=95=E3=82=A9=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E7=AD=89=E3=81=AE=E4=BA=8B=E5=89=8D=E7=8A=B6=E6=85=8B?= =?UTF-8?q?=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E3=82=92=E3=83=89=E3=83=A1?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=82=B5=E3=83=BC=E3=83=93=E3=82=B9=E3=81=A7?= =?UTF-8?q?=E8=A9=B3=E7=B4=B0=E3=81=AB=E8=A1=8C=E3=81=86=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/model/relationship/Relationship.kt | 14 ++++++++++++-- .../relationship/RelationshipDomainService.kt | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt index 87bccaea..813294f7 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt @@ -52,7 +52,7 @@ class Relationship( addDomainEvent(relationshipEventFactory.createEvent(RelationshipEvent.UNFOLLOW_REQUEST)) } - fun block() { + private fun block() { unfollow() blocking = true addDomainEvent(RelationshipEventFactory(this).createEvent(RelationshipEvent.BLOCK)) @@ -81,7 +81,7 @@ class Relationship( mutingFollowRequest = false } - fun followRequest() { + private fun followRequest() { require(blocking.not()) followRequesting = true addDomainEvent(RelationshipEventFactory(this).createEvent(RelationshipEvent.FOLLOW_REQUEST)) @@ -123,6 +123,16 @@ class Relationship( return result } + abstract class InternalRelationshipDomainService { + protected fun block(relationship: Relationship) { + relationship.block() + } + + protected fun followRequest(relationship: Relationship) { + relationship.followRequest() + } + } + companion object { fun default(actorId: ActorId, targetActorId: ActorId): Relationship = Relationship( actorId = actorId, diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/relationship/RelationshipDomainService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/relationship/RelationshipDomainService.kt index b59c0319..7c35d6c0 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/relationship/RelationshipDomainService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/relationship/RelationshipDomainService.kt @@ -17,17 +17,28 @@ package dev.usbharu.hideout.core.domain.service.relationship import dev.usbharu.hideout.core.domain.model.relationship.Relationship +import dev.usbharu.hideout.core.domain.model.relationship.Relationship.InternalRelationshipDomainService import org.springframework.stereotype.Service @Service -class RelationshipDomainService { +class RelationshipDomainService : InternalRelationshipDomainService() { fun block(relationship: Relationship, inverseRelationship: Relationship) { require(relationship != inverseRelationship) require(relationship.actorId == inverseRelationship.targetActorId) require(relationship.targetActorId == inverseRelationship.actorId) - relationship.block() + block(relationship) inverseRelationship.unfollow() inverseRelationship.unfollowRequest() } + + fun followRequest(relationship: Relationship, inverseRelationship: Relationship) { + require(relationship != inverseRelationship) + require(relationship.actorId == inverseRelationship.targetActorId) + require(relationship.targetActorId == inverseRelationship.actorId) + require(inverseRelationship.blocking.not()) + require(relationship.blocking.not()) + + followRequest(relationship) + } } From 22084ee4bef046f67ebfba5f8b07791bb4b4fea1 Mon Sep 17 00:00:00 2001 From: usbharu Date: Wed, 18 Sep 2024 23:31:23 +0900 Subject: [PATCH 45/56] =?UTF-8?q?feat:=20UserFollowRequestApplicationServi?= =?UTF-8?q?ce.kt=E3=82=92=E3=83=95=E3=82=A9=E3=83=AD=E3=83=BC=E5=89=8D?= =?UTF-8?q?=E7=8A=B6=E6=85=8B=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E3=81=AB?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UserFollowRequestApplicationService.kt | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/relationship/UserFollowRequestApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/relationship/UserFollowRequestApplicationService.kt index 0e31b34b..2eee2570 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/relationship/UserFollowRequestApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/relationship/UserFollowRequestApplicationService.kt @@ -24,6 +24,7 @@ import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.relationship.Relationship import dev.usbharu.hideout.core.domain.model.relationship.RelationshipRepository import dev.usbharu.hideout.core.domain.model.support.principal.LocalUser +import dev.usbharu.hideout.core.domain.service.relationship.RelationshipDomainService import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -32,9 +33,9 @@ class UserFollowRequestApplicationService( private val relationshipRepository: RelationshipRepository, transaction: Transaction, private val actorRepository: ActorRepository, + private val relationshipDomainService: RelationshipDomainService ) : LocalUserAbstractApplicationService( - transaction, - logger + transaction, logger ) { override suspend fun internalExecute(command: FollowRequest, principal: LocalUser) { @@ -43,11 +44,15 @@ class UserFollowRequestApplicationService( val targetId = ActorId(command.targetActorId) val relationship = relationshipRepository.findByActorIdAndTargetId(actor.id, targetId) ?: Relationship.default( - actor.id, - targetId + actor.id, targetId ) - relationship.followRequest() + val inverseRelationship = + relationshipRepository.findByActorIdAndTargetId(targetId, actor.id) ?: Relationship.default( + targetId, actor.id + ) + + relationshipDomainService.followRequest(relationship, inverseRelationship) relationshipRepository.save(relationship) } From b52839192c2179789644658e65c992d7c69bfb08 Mon Sep 17 00:00:00 2001 From: usbharu Date: Wed, 18 Sep 2024 23:54:25 +0900 Subject: [PATCH 46/56] =?UTF-8?q?test:=20RelationshipTest.kt=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/relationship/RelationshipTest.kt | 70 +++++++++++-------- .../ExposedRelationshipRepositoryTest.kt | 4 +- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipTest.kt index 7a299558..7a9c514b 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/model/relationship/RelationshipTest.kt @@ -28,24 +28,6 @@ class RelationshipTest { assertContainsEvent(relationship, RelationshipEvent.UNFOLLOW_REQUEST.eventName) } - @Test - fun block_unfollowされblockが発生する() { - val relationship = Relationship( - actorId = ActorId(1), - targetActorId = ActorId(2), - following = true, - blocking = false, - muting = false, - followRequesting = false, - mutingFollowRequest = false - ) - - relationship.block() - - assertTrue(relationship.blocking) - assertContainsEvent(relationship, RelationshipEvent.BLOCK.eventName) - } - @Test fun mute_MUTEが発生する() { val relationship = Relationship( @@ -116,25 +98,55 @@ class RelationshipTest { assertFalse(relationship.mutingFollowRequest) } - @Test - fun followRequest_followRequestingがtrueになりFOLLOW_REQUESTが発生する() { - - } - - @Test - fun followRequest_ブロックしている場合はフォローリクエストを送れない() { - - } - @Test fun unfollowRequest_followRequestingがfalseになりUNFOLLOW_REQUESTが発生する() { + val relationship = Relationship( + ActorId(1), + targetActorId = ActorId(2), + following = false, + blocking = false, + muting = false, + followRequesting = true, + mutingFollowRequest = false + ) + relationship.unfollowRequest() + + assertFalse(relationship.followRequesting) + assertContainsEvent(relationship, RelationshipEvent.UNFOLLOW_REQUEST.eventName) } @Test fun acceptFollowRequest_followingがtrueにfollowRequestingがfalseになりaccept_followが発生する() { + val relationship = Relationship( + actorId = ActorId(1), + targetActorId = ActorId(2), + following = false, + blocking = false, + muting = false, + followRequesting = true, + mutingFollowRequest = true + ) + relationship.acceptFollowRequest() + assertTrue(relationship.following) + assertContainsEvent(relationship, RelationshipEvent.ACCEPT_FOLLOW.eventName) } - + @Test + fun rejectFollowRequest_followRequestingがfalseになりREJECT_FOLLOWが発生する() { + val relationship = Relationship( + actorId = ActorId(1), + targetActorId = ActorId(2), + following = false, + blocking = false, + muting = false, + followRequesting = true, + mutingFollowRequest = false + ) + + relationship.rejectFollowRequest() + assertFalse(relationship.followRequesting) + assertContainsEvent(relationship, RelationshipEvent.REJECT_FOLLOW.eventName) + } } \ No newline at end of file diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedRelationshipRepositoryTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedRelationshipRepositoryTest.kt index 8220d6a2..01d0f5ef 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedRelationshipRepositoryTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedRelationshipRepositoryTest.kt @@ -464,7 +464,7 @@ class ExposedRelationshipRepositoryTest : AbstractRepositoryTest(Relationships) mutingFollowRequest = false, ) - relationship.block() + relationship.mute() repository.save(relationship) @@ -492,7 +492,7 @@ class ExposedRelationshipRepositoryTest : AbstractRepositoryTest(Relationships) followRequesting = false, mutingFollowRequest = false, ) - relationship.block() + relationship.mute() repository.delete(relationship) From 0e0b5bc0ac5e0d01b838af03df16f3857c3f38ed Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Sep 2024 12:20:05 +0000 Subject: [PATCH 47/56] chore(deps): update plugin spring-boot to v3.3.4 --- libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs.versions.toml b/libs.versions.toml index 6654ed59..905dd77b 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -124,7 +124,7 @@ grpc-kotlin = ["grpc-kotlin-stub", "grpc-netty", "grpc-protobuf", "protobuf-kotl [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } -spring-boot = { id = "org.springframework.boot", version = "3.3.3" } +spring-boot = { id = "org.springframework.boot", version = "3.3.4" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } kotlin-spring = { id = "org.jetbrains.kotlin.plugin.spring", version.ref = "kotlin" } kover = { id = "org.jetbrains.kotlinx.kover", version = "0.8.3" } From d2b69b162ae006a19e324e92ba6ca7f3bcc53407 Mon Sep 17 00:00:00 2001 From: usbharu Date: Fri, 20 Sep 2024 14:51:24 +0900 Subject: [PATCH 48/56] =?UTF-8?q?feat:=20Filter=E3=81=AA=E3=81=A9=E3=81=AB?= =?UTF-8?q?toString=E3=81=A8equals=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/domain/model/filter/Filter.kt | 10 +++ .../core/domain/model/filter/FilterKeyword.kt | 10 +++ .../core/domain/model/filter/FilterName.kt | 7 ++ .../core/domain/model/filter/FilterResult.kt | 29 +++++++- .../core/domain/model/filter/FilteredPost.kt | 29 +++++++- .../service/filter/FilterDomainServiceTest.kt | 67 +++++++++++++++++++ 6 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/filter/FilterDomainServiceTest.kt diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/Filter.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/Filter.kt index 43d18485..30878db0 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/Filter.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/Filter.kt @@ -82,6 +82,16 @@ class Filter( } override fun hashCode(): Int = id.hashCode() + override fun toString(): String { + return "Filter(" + + "id=$id, " + + "userDetailId=$userDetailId, " + + "name=$name, " + + "filterContext=$filterContext, " + + "filterAction=$filterAction, " + + "filterKeywords=$filterKeywords" + + ")" + } companion object { fun isAllow(user: UserDetail, action: Action, resource: Filter): Boolean { diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt index fb404f20..f0f2b2d7 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt @@ -33,4 +33,14 @@ class FilterKeyword( override fun hashCode(): Int { return id.hashCode() } + + override fun toString(): String { + return "FilterKeyword(" + + "id=$id, " + + "keyword=$keyword, " + + "mode=$mode" + + ")" + } + + } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt index b88dbf71..bf31e0f9 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt @@ -33,6 +33,13 @@ class FilterName(name: String) { return name.hashCode() } + override fun toString(): String { + return "FilterName(" + + "name='$name'" + + ")" + } + + companion object { const val LENGTH = 300 } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterResult.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterResult.kt index 7bd074c6..b3256ed6 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterResult.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterResult.kt @@ -16,4 +16,31 @@ package dev.usbharu.hideout.core.domain.model.filter -class FilterResult(val filter: Filter, val matchedKeyword: String) +class FilterResult(val filter: Filter, val matchedKeyword: String) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as FilterResult + + if (filter != other.filter) return false + if (matchedKeyword != other.matchedKeyword) return false + + return true + } + + override fun hashCode(): Int { + var result = filter.hashCode() + result = 31 * result + matchedKeyword.hashCode() + return result + } + + override fun toString(): String { + return "FilterResult(" + + "filter=$filter, " + + "matchedKeyword='$matchedKeyword'" + + ")" + } + + +} diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilteredPost.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilteredPost.kt index 5d75f380..c2153101 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilteredPost.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilteredPost.kt @@ -18,4 +18,31 @@ package dev.usbharu.hideout.core.domain.model.filter import dev.usbharu.hideout.core.domain.model.post.Post -class FilteredPost(val post: Post, val filterResults: List) +class FilteredPost(val post: Post, val filterResults: List) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as FilteredPost + + if (post != other.post) return false + if (filterResults != other.filterResults) return false + + return true + } + + override fun hashCode(): Int { + var result = post.hashCode() + result = 31 * result + filterResults.hashCode() + return result + } + + override fun toString(): String { + return "FilteredPost(" + + "post=$post, " + + "filterResults=$filterResults" + + ")" + } + + +} diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/filter/FilterDomainServiceTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/filter/FilterDomainServiceTest.kt new file mode 100644 index 00000000..93505d16 --- /dev/null +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/filter/FilterDomainServiceTest.kt @@ -0,0 +1,67 @@ +package dev.usbharu.hideout.core.domain.service.filter + +import dev.usbharu.hideout.core.domain.model.filter.* +import dev.usbharu.hideout.core.domain.model.post.TestPostFactory +import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailId +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class FilterDomainServiceTest { + @Test + fun apply_filterContextの適用範囲にフィルターが適用される() { + val post = TestPostFactory.create() + + val domainService = FilterDomainService() + val filter = Filter( + FilterId(1), + userDetailId = UserDetailId(1), + FilterName("filter"), + setOf(FilterContext.HOME), + filterAction = FilterAction.HIDE, + setOf(FilterKeyword(FilterKeywordId(1), FilterKeywordKeyword("test"), FilterMode.NONE)) + ) + val apply = domainService.apply(post, FilterContext.HOME, listOf(filter)) + assertEquals(1, apply.filterResults.size) + assertEquals("test", apply.filterResults.first().matchedKeyword) + } + + @Test + fun apply_filterContextに当てはまらないならfilterResultsが空になる() { + val post = TestPostFactory.create() + + val domainService = FilterDomainService() + val filter = Filter( + FilterId(1), + userDetailId = UserDetailId(1), + FilterName("filter"), + setOf(FilterContext.PUBLIC), + filterAction = FilterAction.HIDE, + setOf(FilterKeyword(FilterKeywordId(1), FilterKeywordKeyword("test"), FilterMode.NONE)) + ) + val apply = domainService.apply(post, FilterContext.HOME, listOf(filter)) + assertEquals(0, apply.filterResults.size) + } + + @Test + fun overviewにも適用される() { + val post = TestPostFactory.create(overview = "test") + + val domainService = FilterDomainService() + val filter = Filter( + FilterId(1), + userDetailId = UserDetailId(1), + FilterName("filter"), + setOf(FilterContext.HOME), + filterAction = FilterAction.HIDE, + setOf(FilterKeyword(FilterKeywordId(1), FilterKeywordKeyword("test"), FilterMode.NONE)) + ) + val apply = domainService.apply(post, FilterContext.HOME, listOf(filter)) + assertEquals(2, apply.filterResults.size) + assertEquals("test", apply.filterResults.first().matchedKeyword) + } + + @Test + fun applyAll_filterContextの適用範囲にフィルターが適用される() { + + } +} \ No newline at end of file From 9bc5f01c9b982feffee5445395c7050b662467a6 Mon Sep 17 00:00:00 2001 From: usbharu Date: Sat, 21 Sep 2024 15:56:30 +0900 Subject: [PATCH 49/56] =?UTF-8?q?test:=20DefaultPostReadAccessControl?= =?UTF-8?q?=E3=81=AB=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/DefaultPostReadAccessControl.kt | 10 +- .../service/filter/FilterDomainServiceTest.kt | 19 ++ .../post/DefaultPostReadAccessControlTest.kt | 220 +++++++++++++++++- 3 files changed, 242 insertions(+), 7 deletions(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControl.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControl.kt index 280bc9bb..e9c1c2ad 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControl.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControl.kt @@ -77,12 +77,12 @@ class DefaultPostReadAccessControl(private val relationshipRepository: Relations override suspend fun areAllows(postList: List, principal: Principal): List { val actorIds = postList.map { it.actorId } - val relationshipList = + val blockedByList = relationshipRepository.findByActorIdsAndTargetIdAndBlocking(actorIds, principal.actorId, true) .map { it.actorId } - val inverseRelationshipList = + val followingList = relationshipRepository.findByActorIdAndTargetIdsAndFollowing(principal.actorId, actorIds, true) - .map { it.actorId } + .map { it.targetActorId } fun internalAllow(post: Post): Boolean { // ポスト主は無条件で見れる @@ -90,7 +90,7 @@ class DefaultPostReadAccessControl(private val relationshipRepository: Relations return true } - if (relationshipList.contains(post.actorId)) { + if (blockedByList.contains(post.actorId)) { return false } @@ -106,7 +106,7 @@ class DefaultPostReadAccessControl(private val relationshipRepository: Relations return true } - if (post.visibility == Visibility.FOLLOWERS && inverseRelationshipList.contains(principal.actorId)) { + if (post.visibility == Visibility.FOLLOWERS && followingList.contains(post.actorId)) { return true } return false diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/filter/FilterDomainServiceTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/filter/FilterDomainServiceTest.kt index 93505d16..6d43550a 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/filter/FilterDomainServiceTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/filter/FilterDomainServiceTest.kt @@ -62,6 +62,25 @@ class FilterDomainServiceTest { @Test fun applyAll_filterContextの適用範囲にフィルターが適用される() { + val postList = listOf( + TestPostFactory.create(), + TestPostFactory.create(), + TestPostFactory.create(content = "aaaaaaaaaa"), + TestPostFactory.create(), + TestPostFactory.create() + ) + val filter = Filter( + FilterId(1), + userDetailId = UserDetailId(1), + FilterName("filter"), + setOf(FilterContext.HOME), + filterAction = FilterAction.HIDE, + setOf(FilterKeyword(FilterKeywordId(1), FilterKeywordKeyword("test"), FilterMode.NONE)) + ) + + val filteredPosts = FilterDomainService().applyAll(postList, FilterContext.HOME, filters = listOf(filter)) + + assertEquals(5, filteredPosts.size) } } \ No newline at end of file diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControlTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControlTest.kt index 5340309f..16736b6c 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControlTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/post/DefaultPostReadAccessControlTest.kt @@ -1,6 +1,7 @@ package dev.usbharu.hideout.core.domain.service.post import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.post.Post import dev.usbharu.hideout.core.domain.model.post.TestPostFactory import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.domain.model.relationship.Relationship @@ -13,12 +14,14 @@ import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertAll import org.junit.jupiter.api.extension.ExtendWith import org.mockito.InjectMocks import org.mockito.Mock import org.mockito.junit.jupiter.MockitoExtension -import org.mockito.kotlin.doReturn -import org.mockito.kotlin.whenever +import org.mockito.kotlin.* +import kotlin.test.assertContentEquals +import kotlin.test.assertEquals @ExtendWith(MockitoExtension::class) class DefaultPostReadAccessControlTest { @@ -155,4 +158,217 @@ class DefaultPostReadAccessControlTest { assertFalse(actual) } + + @Test + fun ポスト主は無条件で見れる() = runTest { + val actual = service.isAllow( + TestPostFactory.create(actorId = 1, visibility = Visibility.DIRECT), + LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com")) + ) + + assertTrue(actual) + } + + @Test + fun areAllows_ポスト主は無条件で見れる() = runTest { + whenever( + relationshipRepository.findByActorIdsAndTargetIdAndBlocking( + any(), + anyValueClass(), + eq(true) + ) + ).doReturn( + emptyList() + ) + whenever( + relationshipRepository.findByActorIdAndTargetIdsAndFollowing( + anyValueClass(), + any(), + eq(true) + ) + ).doReturn( + emptyList() + ) + + val postList = listOf( + TestPostFactory.create(actorId = 1, visibility = Visibility.DIRECT), + TestPostFactory.create(actorId = 1, visibility = Visibility.FOLLOWERS), + TestPostFactory.create(actorId = 1, visibility = Visibility.UNLISTED), + TestPostFactory.create(actorId = 1, visibility = Visibility.PUBLIC), + ) + val actual = service.areAllows(postList, LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))) + + assertContentEquals(postList, actual) + } + + @Test + fun areFollows_ブロックされていたら見れない() = runTest { + whenever( + relationshipRepository.findByActorIdsAndTargetIdAndBlocking( + any(), + anyValueClass(), + eq(true) + ) + ).doReturn( + listOf(Relationship.default(actorId = ActorId(2), targetActorId = ActorId(1))) + ) + whenever( + relationshipRepository.findByActorIdAndTargetIdsAndFollowing( + anyValueClass(), + any(), + eq(true) + ) + ).doReturn( + emptyList() + ) + + val postList = listOf( + TestPostFactory.create(actorId = 1, visibility = Visibility.DIRECT), + TestPostFactory.create(actorId = 2, visibility = Visibility.FOLLOWERS), + TestPostFactory.create(actorId = 1, visibility = Visibility.UNLISTED), + TestPostFactory.create(actorId = 1, visibility = Visibility.PUBLIC), + ) + val actual = service.areAllows(postList, LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))) + + assertEquals(3, actual.size) + assertAll(actual.map { { assertEquals(1, it.actorId.id) } }) + } + + + @Test + fun areAllows_PUBLICとUNLISTEDは見れる() = runTest { + whenever( + relationshipRepository.findByActorIdsAndTargetIdAndBlocking( + any(), + anyValueClass(), + eq(true) + ) + ).doReturn( + emptyList() + ) + whenever( + relationshipRepository.findByActorIdAndTargetIdsAndFollowing( + anyValueClass(), + any(), + eq(true) + ) + ).doReturn( + emptyList() + ) + + val postList = listOf( + TestPostFactory.create(actorId = 3, visibility = Visibility.DIRECT), + TestPostFactory.create(actorId = 3, visibility = Visibility.FOLLOWERS), + TestPostFactory.create(actorId = 3, visibility = Visibility.UNLISTED), + TestPostFactory.create(actorId = 3, visibility = Visibility.PUBLIC), + ) + val actual = service.areAllows(postList, LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))) + + assertEquals(2, actual.size) + kotlin.test.assertTrue(actual.all { it.visibility == Visibility.PUBLIC || it.visibility == Visibility.UNLISTED }) + } + + @Test + fun areAllows_Anonymousは見れない() = runTest { + whenever( + relationshipRepository.findByActorIdsAndTargetIdAndBlocking( + any(), + anyValueClass(), + eq(true) + ) + ).doReturn( + emptyList() + ) + whenever( + relationshipRepository.findByActorIdAndTargetIdsAndFollowing( + anyValueClass(), + any(), + eq(true) + ) + ).doReturn( + emptyList() + ) + + val postList = listOf( + TestPostFactory.create(actorId = 3, visibility = Visibility.DIRECT), + TestPostFactory.create(actorId = 3, visibility = Visibility.FOLLOWERS), + TestPostFactory.create(actorId = 3, visibility = Visibility.UNLISTED), + TestPostFactory.create(actorId = 3, visibility = Visibility.PUBLIC), + ) + val actual = service.areAllows(postList, Anonymous) + + assertEquals(2, actual.size) + kotlin.test.assertTrue(actual.all { it.visibility == Visibility.PUBLIC || it.visibility == Visibility.UNLISTED }) + } + + @Test + fun areAllows_DIRECTはVisibleActorsに入っていたら見れる() = runTest { + whenever( + relationshipRepository.findByActorIdsAndTargetIdAndBlocking( + any(), + anyValueClass(), + eq(true) + ) + ).doReturn( + emptyList() + ) + whenever( + relationshipRepository.findByActorIdAndTargetIdsAndFollowing( + anyValueClass(), + any(), + eq(true) + ) + ).doReturn( + emptyList() + ) + + val postList = listOf( + TestPostFactory.create(id = 1, actorId = 3, visibility = Visibility.DIRECT, visibleActors = listOf(1)), + TestPostFactory.create(id = 2, actorId = 3, visibility = Visibility.DIRECT, visibleActors = listOf(2)), + TestPostFactory.create(id = 3, actorId = 3, visibility = Visibility.DIRECT, visibleActors = listOf(3)), + TestPostFactory.create( + id = 4, + actorId = 3, + visibility = Visibility.DIRECT, + visibleActors = listOf(1, 2, 3, 4) + ), + ) + val actual = service.areAllows(postList, LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))) + + assertEquals(2, actual.size) + kotlin.test.assertTrue(actual.all { it.id.id == 1L || it.id.id == 4L }) + } + + @Test + fun areAllows_FOLLOWERSはフォローされていたら見れる() = runTest { + whenever( + relationshipRepository.findByActorIdsAndTargetIdAndBlocking( + any(), + anyValueClass(), + eq(true) + ) + ).doReturn( + emptyList() + ) + whenever( + relationshipRepository.findByActorIdAndTargetIdsAndFollowing( + anyValueClass(), + any(), + eq(true) + ) + ).doReturn( + listOf(Relationship.default(actorId = ActorId(1), targetActorId = ActorId(2))) + ) + + val postList = listOf( + TestPostFactory.create(actorId = 3, visibility = Visibility.FOLLOWERS), + TestPostFactory.create(actorId = 2, visibility = Visibility.FOLLOWERS), + TestPostFactory.create(actorId = 3, visibility = Visibility.FOLLOWERS), + TestPostFactory.create(actorId = 3, visibility = Visibility.FOLLOWERS), + ) + val actual = service.areAllows(postList, LocalUser(ActorId(1), UserDetailId(1), Acct("test", "example.com"))) + + assertEquals(1, actual.size) + assertAll(actual.map { { assertEquals(2, it.actorId.id) } }) + } } \ No newline at end of file From 857beccd59ae4ea20f670b5e9372c69739d04a3b Mon Sep 17 00:00:00 2001 From: usbharu Date: Sat, 21 Sep 2024 17:10:49 +0900 Subject: [PATCH 50/56] =?UTF-8?q?test:=20RelationshipDomainService?= =?UTF-8?q?=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RelationshipDomainServiceTest.kt | 136 ++++++++++++++++++ .../userdetail/UserDetailDomainServiceTest.kt | 28 ++++ 2 files changed, 164 insertions(+) create mode 100644 hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/relationship/RelationshipDomainServiceTest.kt create mode 100644 hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/userdetail/UserDetailDomainServiceTest.kt diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/relationship/RelationshipDomainServiceTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/relationship/RelationshipDomainServiceTest.kt new file mode 100644 index 00000000..df5886da --- /dev/null +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/relationship/RelationshipDomainServiceTest.kt @@ -0,0 +1,136 @@ +package dev.usbharu.hideout.core.domain.service.relationship + +import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.relationship.Relationship +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class RelationshipDomainServiceTest { + @Test + fun block_relationshipとinverseRelationshipが同じ場合失敗() { + val relationship = Relationship.default(ActorId(1), ActorId(2)) + assertThrows { + RelationshipDomainService().block(relationship, relationship) + } + } + + @Test + fun block_relationship_actorIdとinverseRelationshio_targetActorIdが同じ場合失敗() { + val relationship = Relationship.default(ActorId(1), ActorId(2)) + val inverseRelationship = Relationship.default(ActorId(2), ActorId(2)) + assertThrows { + RelationshipDomainService().block(relationship, inverseRelationship) + } + } + + @Test + fun block_relationship_targetActorIdとinverseRelationship_actorIdが同じ場合失敗() { + val relationship = Relationship.default(ActorId(1), ActorId(2)) + val inverseRelationship = Relationship.default(ActorId(1), ActorId(1)) + assertThrows { + RelationshipDomainService().block(relationship, inverseRelationship) + } + } + + @Test + fun block_ブロックされお互いのフォローとフォローリクエストが外れる() { + val relationship = Relationship( + ActorId(1), + ActorId(2), + following = true, + blocking = false, + muting = false, + followRequesting = false, + mutingFollowRequest = false + ) + val inverseRelationship = Relationship( + ActorId(2), + ActorId(1), + following = false, + blocking = false, + followRequesting = true, + mutingFollowRequest = false, + muting = false + ) + + RelationshipDomainService().block(relationship, inverseRelationship) + + assertTrue(relationship.blocking) + assertFalse(relationship.following) + assertFalse(relationship.followRequesting) + assertFalse(inverseRelationship.following) + assertFalse(inverseRelationship.followRequesting) + } + + @Test + fun followRequest_relationshipとinverseRelationshipが同じ場合失敗() { + val relationship = Relationship.default(ActorId(1), ActorId(2)) + assertThrows { + RelationshipDomainService().followRequest(relationship, relationship) + } + } + + @Test + fun followRequest_relationship_actorIdとinverseRelationshio_targetActorIdが同じ場合失敗() { + val relationship = Relationship.default(ActorId(1), ActorId(2)) + val inverseRelationship = Relationship.default(ActorId(2), ActorId(2)) + assertThrows { + RelationshipDomainService().followRequest(relationship, inverseRelationship) + } + } + + @Test + fun followRequest_relationship_targetActorIdとinverseRelationship_actorIdが同じ場合失敗() { + val relationship = Relationship.default(ActorId(1), ActorId(2)) + val inverseRelationship = Relationship.default(ActorId(1), ActorId(1)) + assertThrows { + RelationshipDomainService().followRequest(relationship, inverseRelationship) + } + } + + @Test + fun followRequest_ブロックされてる場合失敗() { + val relationship = Relationship.default(ActorId(1), ActorId(2)) + val inverseRelationship = Relationship( + ActorId(2), + ActorId(1), + following = false, + blocking = true, + muting = false, + followRequesting = false, + mutingFollowRequest = false + ) + assertThrows { + RelationshipDomainService().followRequest(relationship, inverseRelationship) + } + } + + @Test + fun followRequest_ブロックしてる場合は失敗() { + val relationship = Relationship( + ActorId(1), + ActorId(2), + following = false, + blocking = true, + muting = false, + followRequesting = false, + mutingFollowRequest = false + ) + val inverseRelationship = Relationship.default(ActorId(2), ActorId(1)) + assertThrows { + RelationshipDomainService().followRequest(relationship, inverseRelationship) + } + } + + @Test + fun followRequest_followRequestingがtrueになる() { + val relationship = Relationship.default(ActorId(1), ActorId(2)) + val inverseRelationship = Relationship.default(ActorId(2), ActorId(1)) + + RelationshipDomainService().followRequest(relationship, inverseRelationship) + + assertTrue(relationship.followRequesting) + } +} \ No newline at end of file diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/userdetail/UserDetailDomainServiceTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/userdetail/UserDetailDomainServiceTest.kt new file mode 100644 index 00000000..fa75ff66 --- /dev/null +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/userdetail/UserDetailDomainServiceTest.kt @@ -0,0 +1,28 @@ +package dev.usbharu.hideout.core.domain.service.userdetail + +import dev.usbharu.hideout.core.infrastructure.springframework.SpringSecurityPasswordEncoder +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.InjectMocks +import org.mockito.Spy +import org.mockito.junit.jupiter.MockitoExtension +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder +import kotlin.test.assertNotEquals + +@ExtendWith(MockitoExtension::class) +class UserDetailDomainServiceTest { + + @InjectMocks + lateinit var userDetailDomainService: UserDetailDomainService + + @Spy + val passwordEncoder: PasswordEncoder = SpringSecurityPasswordEncoder(BCryptPasswordEncoder()) + + @Test + fun hash() = runTest { + val hashedPassword = userDetailDomainService.hashPassword("password") + + assertNotEquals("password", hashedPassword.password) + } +} \ No newline at end of file From 5777adac93e15af820f997b6370e69f9148cd9f0 Mon Sep 17 00:00:00 2001 From: usbharu Date: Sat, 21 Sep 2024 08:15:47 +0000 Subject: [PATCH 51/56] style: fix lint (CI) --- .../UserFollowRequestApplicationService.kt | 3 ++- .../hideout/core/domain/model/filter/Filter.kt | 14 +++++++------- .../core/domain/model/filter/FilterKeyword.kt | 10 ++++------ .../hideout/core/domain/model/filter/FilterName.kt | 5 ++--- .../core/domain/model/filter/FilterResult.kt | 8 +++----- .../core/domain/model/filter/FilteredPost.kt | 8 +++----- 6 files changed, 21 insertions(+), 27 deletions(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/relationship/UserFollowRequestApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/relationship/UserFollowRequestApplicationService.kt index 2eee2570..0b5aaecc 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/relationship/UserFollowRequestApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/relationship/UserFollowRequestApplicationService.kt @@ -35,7 +35,8 @@ class UserFollowRequestApplicationService( private val actorRepository: ActorRepository, private val relationshipDomainService: RelationshipDomainService ) : LocalUserAbstractApplicationService( - transaction, logger + transaction, + logger ) { override suspend fun internalExecute(command: FollowRequest, principal: LocalUser) { diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/Filter.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/Filter.kt index 30878db0..030c2deb 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/Filter.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/Filter.kt @@ -84,13 +84,13 @@ class Filter( override fun hashCode(): Int = id.hashCode() override fun toString(): String { return "Filter(" + - "id=$id, " + - "userDetailId=$userDetailId, " + - "name=$name, " + - "filterContext=$filterContext, " + - "filterAction=$filterAction, " + - "filterKeywords=$filterKeywords" + - ")" + "id=$id, " + + "userDetailId=$userDetailId, " + + "name=$name, " + + "filterContext=$filterContext, " + + "filterAction=$filterAction, " + + "filterKeywords=$filterKeywords" + + ")" } companion object { diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt index f0f2b2d7..8654a738 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt @@ -36,11 +36,9 @@ class FilterKeyword( override fun toString(): String { return "FilterKeyword(" + - "id=$id, " + - "keyword=$keyword, " + - "mode=$mode" + - ")" + "id=$id, " + + "keyword=$keyword, " + + "mode=$mode" + + ")" } - - } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt index bf31e0f9..39a47259 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt @@ -35,11 +35,10 @@ class FilterName(name: String) { override fun toString(): String { return "FilterName(" + - "name='$name'" + - ")" + "name='$name'" + + ")" } - companion object { const val LENGTH = 300 } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterResult.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterResult.kt index b3256ed6..8c590718 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterResult.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterResult.kt @@ -37,10 +37,8 @@ class FilterResult(val filter: Filter, val matchedKeyword: String) { override fun toString(): String { return "FilterResult(" + - "filter=$filter, " + - "matchedKeyword='$matchedKeyword'" + - ")" + "filter=$filter, " + + "matchedKeyword='$matchedKeyword'" + + ")" } - - } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilteredPost.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilteredPost.kt index c2153101..2b4934c0 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilteredPost.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilteredPost.kt @@ -39,10 +39,8 @@ class FilteredPost(val post: Post, val filterResults: List) { override fun toString(): String { return "FilteredPost(" + - "post=$post, " + - "filterResults=$filterResults" + - ")" + "post=$post, " + + "filterResults=$filterResults" + + ")" } - - } From b0ee6b117ec94db0c3813577d1f311c528aed811 Mon Sep 17 00:00:00 2001 From: usbharu Date: Sat, 21 Sep 2024 17:27:16 +0900 Subject: [PATCH 52/56] style: fix lint --- .../usbharu/hideout/core/domain/model/filter/FilterKeyword.kt | 4 +--- .../usbharu/hideout/core/domain/model/filter/FilterName.kt | 4 +--- .../hideout/core/domain/model/relationship/Relationship.kt | 1 + .../infrastructure/exposedrepository/AbstractRepository.kt | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt index 8654a738..ff139522 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterKeyword.kt @@ -30,9 +30,7 @@ class FilterKeyword( return id == other.id } - override fun hashCode(): Int { - return id.hashCode() - } + override fun hashCode(): Int = id.hashCode() override fun toString(): String { return "FilterKeyword(" + diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt index 39a47259..64c5dd67 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/filter/FilterName.kt @@ -29,9 +29,7 @@ class FilterName(name: String) { return name == other.name } - override fun hashCode(): Int { - return name.hashCode() - } + override fun hashCode(): Int = name.hashCode() override fun toString(): String { return "FilterName(" + diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt index 813294f7..ebb9753a 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/relationship/Relationship.kt @@ -123,6 +123,7 @@ class Relationship( return result } + @Suppress("UnnecessaryAbstractClass") abstract class InternalRelationshipDomainService { protected fun block(relationship: Relationship) { relationship.block() diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/AbstractRepository.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/AbstractRepository.kt index 9b04ca18..534aa0e6 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/AbstractRepository.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/AbstractRepository.kt @@ -27,7 +27,7 @@ import org.springframework.beans.factory.annotation.Value import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator import java.sql.SQLException -@Suppress("VarCouldBeVal") +@Suppress("VarCouldBeVal", "UnnecessaryAbstractClass") abstract class AbstractRepository(protected val logger: Logger) { private val sqlErrorCodeSQLExceptionTranslator = SQLErrorCodeSQLExceptionTranslator() private val springDataAccessExceptionSQLExceptionTranslator = SpringDataAccessExceptionSQLExceptionTranslator() From 386b8a0ec3845610c42f26b9e333cd4034bed9d3 Mon Sep 17 00:00:00 2001 From: usbharu Date: Sun, 22 Sep 2024 11:09:19 +0900 Subject: [PATCH 53/56] =?UTF-8?q?=E4=BD=9C=E3=82=8A=E7=9B=B4=E3=81=97?= =?UTF-8?q?=E3=81=AE=E5=BD=B1=E9=9F=BF=E3=81=A7=E3=82=81=E3=81=A3=E3=81=A1?= =?UTF-8?q?=E3=82=83=E5=98=98=E3=81=A4=E3=81=84=E3=81=A6=E3=81=9FREADME.md?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 74 +------------------------------------------------------ 1 file changed, 1 insertion(+), 73 deletions(-) diff --git a/README.md b/README.md index 2356ce11..0862a37c 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,3 @@ # Hideout -HideoutはMastodon互換APIを備えたSNSで、ActivityPubに対応し、KotlinとSpring Frameworkを使用して制作されているソフトウェアです。現在は開発中で、SNSとして主要な機能を備えていますが、セキュリティの問題や不安定なテーブル定義などがあるためホストすることはおすすめしません。 - -## 特徴 - -### ActivityPubでつながるネットワーク - -ActivityPubを実装しているためMastodonやMisskey、Pleromaとつながることができます。また、ActivityPub以外の分散型の通信プロトコルを実装することがあるかもしれません。 - -### Mastodon互換API - -OAuth2プロバイダーを含めたほとんどのAPIがMastodonとの互換性を持っているため、既存のMastodon クライアントを使用することができます!また、今後Fedibirdやglitch-soc互換のAPIを実装するかもしれません。 - -## セルフホスト - -> [!CAUTION] -> **免責事項** -> -> 本ソフトウェアを利用して発生したすべての事象に対して開発者は責任を負いません。 -> 本ソフトウェアはApache License 2.0を採用しています。 - -現時点でセルフホストはおすすめしませんが、実験用としてホストすることはできます! - -### 使用技術 - -- **Kotlin** 強力な言語機能でアプリケーションの安全性を高めます。 -- **Spring Framework** (Spring Boot/Spring Security/Spring Web/Spring Data) 豊富な機能と堅牢なライブラリでソフトウェアの基幹部分を担います。 -- **OpenAPI** スキーマファーストのエンドポイント自動生成はAPIの安定性を高めます。 - -### 要件 - -#### 起動 - -- Java 21 -- PostgreSQL 12+ -- MongoDB(必須でない) 4.4.x+ - -#### ビルド - -- Java 21 -- Gradle 8+ - -実験用途として、PostgreSQLはH2DB(バンドル)のPostgreSQL互換モードでも問題ありません。 - -Java 17でもビルド/起動ができますが、サポートしません。 - -MongoDBを使用しない場合、構成で`hideout.use-mongodb`をfalseにする必要があります。 - -### ビルド - -今後のリリースでビルド済みjarなどを使う場合はスキップしてください。 - - -```bash -gradle bootJar -``` - -`build/libs/hideout-x.x.x.jar`が生成されます。 - -### 起動 - -適切に設定した`application-dev.yml`などをクラスパス上に準備します。 - -`dev`は`prod`などに置き換えたり、[複数指定すること](https://spring.pleiades.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.core.spring.profiles.active)もできます。 - -```bash -java -jar build/libs/hideout-x.x.x.jar --spring.profiles.active=dev -``` - -https://spring.pleiades.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started.first-application.executable-jar.gradle - -### 注意事項 - -本ソフトウェアは開発中です。正常に機能しない場合があります。また、連合先に迷惑をかける事になる可能性があります。DB/設定ファイル/その他リソースなどの利用方法に破壊的な変更が入る可能性があります。 +ActivityPubで繋がれるSNSを目指している \ No newline at end of file From 309ea569e804150361e85c04d1f4843380dff5dd Mon Sep 17 00:00:00 2001 From: usbharu Date: Sun, 22 Sep 2024 11:40:12 +0900 Subject: [PATCH 54/56] =?UTF-8?q?fix:=20=E3=83=9D=E3=83=BC=E3=83=88?= =?UTF-8?q?=E7=95=AA=E5=8F=B7=E3=82=92=E3=81=97=E3=81=A3=E3=81=8B=E3=82=8A?= =?UTF-8?q?=E6=89=B1=E3=81=88=E3=81=A6=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F?= =?UTF-8?q?=E3=81=AE=E3=81=A7=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../actor/GetActorDetailApplicationService.kt | 3 ++- .../actor/RegisterLocalActorApplicationService.kt | 2 +- .../instance/GetLocalInstanceApplicationService.kt | 2 +- .../instance/InitLocalInstanceApplicationService.kt | 9 +++++---- .../hideout/core/application/model/ActorDetail.kt | 3 ++- .../hideout/core/config/ApplicationConfig.kt | 4 ++-- .../core/domain/model/support/domain/Domain.kt | 13 ++++++++++++- .../service/actor/RemoteActorCheckDomainService.kt | 3 ++- .../actor/local/LocalActorDomainServiceImpl.kt | 3 ++- .../core/infrastructure/factory/ActorFactoryImpl.kt | 3 ++- .../oauth2/UserDetailsServiceImpl.kt | 3 ++- 11 files changed, 33 insertions(+), 15 deletions(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt index 5bcf059b..19c8ca54 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt @@ -24,6 +24,7 @@ import dev.usbharu.hideout.core.domain.model.actor.ActorId import dev.usbharu.hideout.core.domain.model.actor.ActorRepository import dev.usbharu.hideout.core.domain.model.media.MediaRepository import dev.usbharu.hideout.core.domain.model.support.acct.Acct +import dev.usbharu.hideout.core.domain.model.support.domain.apHost import dev.usbharu.hideout.core.domain.model.support.principal.Principal import org.slf4j.LoggerFactory import org.springframework.stereotype.Component @@ -45,7 +46,7 @@ class GetActorDetailApplicationService( ?: throw IllegalArgumentException("Actor ${command.id} not found.") } else if (command.actorName != null) { val host = if (command.actorName.host.isEmpty()) { - applicationConfig.url.host + applicationConfig.url.apHost } else { command.actorName.host } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/RegisterLocalActorApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/RegisterLocalActorApplicationService.kt index 27f2eae0..1c1796bd 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/RegisterLocalActorApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/RegisterLocalActorApplicationService.kt @@ -51,7 +51,7 @@ class RegisterLocalActorApplicationService( if (actorDomainService.usernameAlreadyUse(command.name)) { throw IllegalArgumentException("Username already exists") } - val instance = instanceRepository.findByUrl(applicationConfig.url.toURI()) + val instance = instanceRepository.findByUrl(applicationConfig.url) ?: throw InternalServerException("Local instance not found.") val actor = actorFactoryImpl.createLocal( diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt index dfaf121e..c8c1dbc7 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt @@ -46,7 +46,7 @@ class GetLocalInstanceApplicationService( } val instance = ( - instanceRepository.findByUrl(applicationConfig.url.toURI()) + instanceRepository.findByUrl(applicationConfig.url) ?: throw InternalServerException("Local instance not found.") ) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/InitLocalInstanceApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/InitLocalInstanceApplicationService.kt index 77d2e41b..9a05f9d1 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/InitLocalInstanceApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/InitLocalInstanceApplicationService.kt @@ -19,6 +19,7 @@ package dev.usbharu.hideout.core.application.instance import dev.usbharu.hideout.core.application.shared.Transaction import dev.usbharu.hideout.core.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.instance.* +import dev.usbharu.hideout.core.domain.model.support.domain.apHost import dev.usbharu.hideout.core.domain.shared.id.IdGenerateService import org.springframework.boot.context.event.ApplicationReadyEvent import org.springframework.boot.info.BuildProperties @@ -36,15 +37,15 @@ class InitLocalInstanceApplicationService( ) { @EventListener(ApplicationReadyEvent::class) suspend fun init() = transaction.transaction { - val findByUrl = instanceRepository.findByUrl(applicationConfig.url.toURI()) + val findByUrl = instanceRepository.findByUrl(applicationConfig.url) if (findByUrl == null) { val instance = Instance( id = InstanceId(idGenerateService.generateId()), - name = InstanceName(applicationConfig.url.host), + name = InstanceName(applicationConfig.url.apHost), description = InstanceDescription(""), - url = applicationConfig.url.toURI(), - iconUrl = applicationConfig.url.toURI(), + url = applicationConfig.url, + iconUrl = applicationConfig.url, sharedInbox = null, software = InstanceSoftware("hideout"), version = InstanceVersion(buildProperties.version), diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/model/ActorDetail.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/model/ActorDetail.kt index 7cbdd246..834abf77 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/model/ActorDetail.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/model/ActorDetail.kt @@ -18,6 +18,7 @@ package dev.usbharu.hideout.core.application.model import dev.usbharu.hideout.core.domain.model.actor.Actor import dev.usbharu.hideout.core.domain.model.media.Media +import dev.usbharu.hideout.core.domain.model.support.domain.apHost import java.net.URI data class ActorDetail( @@ -41,7 +42,7 @@ data class ActorDetail( id = actor.id.id, name = actor.name.name, screenName = actor.screenName.screenName, - host = actor.url.host, + host = actor.url.apHost, instanceId = actor.instance.instanceId, remoteUrl = actor.url, locked = actor.locked, diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/ApplicationConfig.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/ApplicationConfig.kt index 5cb5941c..8a91aae0 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/ApplicationConfig.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/ApplicationConfig.kt @@ -17,11 +17,11 @@ package dev.usbharu.hideout.core.config import org.springframework.boot.context.properties.ConfigurationProperties -import java.net.URL +import java.net.URI @ConfigurationProperties("hideout") data class ApplicationConfig( - val url: URL, + val url: URI, val private: Boolean = true, val keySize: Int = 2048, ) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/domain/Domain.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/domain/Domain.kt index b17ab7bd..813be1d6 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/domain/Domain.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/domain/Domain.kt @@ -16,6 +16,8 @@ package dev.usbharu.hideout.core.domain.model.support.domain +import java.net.URI + @JvmInline value class Domain(val domain: String) { init { @@ -23,6 +25,15 @@ value class Domain(val domain: String) { } companion object { - const val LENGTH = 1000 + const val LENGTH: Int = 1000 + + fun of(uri: URI): Domain = Domain(uri.apHost) } } + +val URI.apHost: String + get() = if (port == -1) { + host + } else { + "$host:$port" + } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/actor/RemoteActorCheckDomainService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/actor/RemoteActorCheckDomainService.kt index a2f9b6fd..b32446e4 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/actor/RemoteActorCheckDomainService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/actor/RemoteActorCheckDomainService.kt @@ -18,6 +18,7 @@ package dev.usbharu.hideout.core.domain.service.actor import dev.usbharu.hideout.core.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.actor.Actor +import dev.usbharu.hideout.core.domain.model.support.domain.apHost import org.springframework.stereotype.Service interface IRemoteActorCheckDomainService { @@ -26,5 +27,5 @@ interface IRemoteActorCheckDomainService { @Service class RemoteActorCheckDomainService(private val applicationConfig: ApplicationConfig) : IRemoteActorCheckDomainService { - override fun isRemoteActor(actor: Actor): Boolean = actor.domain.domain != applicationConfig.url.host + override fun isRemoteActor(actor: Actor): Boolean = actor.domain.domain != applicationConfig.url.apHost } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/actor/local/LocalActorDomainServiceImpl.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/actor/local/LocalActorDomainServiceImpl.kt index 6f0dd6de..b4cba69d 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/actor/local/LocalActorDomainServiceImpl.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/service/actor/local/LocalActorDomainServiceImpl.kt @@ -20,6 +20,7 @@ import dev.usbharu.hideout.core.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.actor.ActorPrivateKey import dev.usbharu.hideout.core.domain.model.actor.ActorPublicKey import dev.usbharu.hideout.core.domain.model.actor.ActorRepository +import dev.usbharu.hideout.core.domain.model.support.domain.apHost import org.springframework.stereotype.Service import java.security.KeyPairGenerator @@ -29,7 +30,7 @@ class LocalActorDomainServiceImpl( private val applicationConfig: ApplicationConfig, ) : LocalActorDomainService { override suspend fun usernameAlreadyUse(name: String): Boolean = - actorRepository.findByNameAndDomain(name, applicationConfig.url.host) != null + actorRepository.findByNameAndDomain(name, applicationConfig.url.apHost) != null override suspend fun generateKeyPair(): Pair { val keyPairGenerator = KeyPairGenerator.getInstance("RSA") diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/ActorFactoryImpl.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/ActorFactoryImpl.kt index 9c41792b..1d00d00d 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/ActorFactoryImpl.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/factory/ActorFactoryImpl.kt @@ -20,6 +20,7 @@ import dev.usbharu.hideout.core.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.actor.* import dev.usbharu.hideout.core.domain.model.instance.InstanceId import dev.usbharu.hideout.core.domain.model.support.domain.Domain +import dev.usbharu.hideout.core.domain.model.support.domain.apHost import dev.usbharu.hideout.core.domain.shared.id.IdGenerateService import org.springframework.stereotype.Component import java.net.URI @@ -40,7 +41,7 @@ class ActorFactoryImpl( return Actor( id = ActorId(idGenerateService.generateId()), name = actorName, - domain = Domain(applicationConfig.url.host), + domain = Domain(applicationConfig.url.apHost), screenName = ActorScreenName(name), description = ActorDescription(""), inbox = URI.create("$userUrl/inbox"), diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt index 713374bd..2fa8ebe2 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImpl.kt @@ -19,6 +19,7 @@ package dev.usbharu.hideout.core.infrastructure.springframework.oauth2 import dev.usbharu.hideout.core.application.shared.Transaction import dev.usbharu.hideout.core.config.ApplicationConfig import dev.usbharu.hideout.core.domain.model.actor.ActorRepository +import dev.usbharu.hideout.core.domain.model.support.domain.apHost import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository import kotlinx.coroutines.runBlocking import kotlinx.coroutines.slf4j.MDCContext @@ -39,7 +40,7 @@ class UserDetailsServiceImpl( throw UsernameNotFoundException("Username not found") } transaction.transaction { - val actor = actorRepository.findByNameAndDomain(username, applicationConfig.url.host) + val actor = actorRepository.findByNameAndDomain(username, applicationConfig.url.apHost) ?: throw UsernameNotFoundException("$username not found") val userDetail = userDetailRepository.findByActorId(actor.id.id) ?: throw UsernameNotFoundException("${actor.id.id} not found") From 96d51a885fd22b301d8b038dafa653fccede61f5 Mon Sep 17 00:00:00 2001 From: usbharu Date: Sun, 22 Sep 2024 11:43:19 +0900 Subject: [PATCH 55/56] =?UTF-8?q?test:=20=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=82=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../actor/RegisterLocalActorApplicationServiceTest.kt | 4 ++-- .../domain/service/actor/RemoteActorCheckDomainServiceTest.kt | 4 ++-- .../service/actor/local/LocalActorDomainServiceImplTest.kt | 4 ++-- .../springframework/oauth2/UserDetailsServiceImplTest.kt | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/application/actor/RegisterLocalActorApplicationServiceTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/application/actor/RegisterLocalActorApplicationServiceTest.kt index e0087535..309f41cf 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/application/actor/RegisterLocalActorApplicationServiceTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/application/actor/RegisterLocalActorApplicationServiceTest.kt @@ -22,7 +22,7 @@ import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.whenever import utils.TestTransaction -import java.net.URL +import java.net.URI @ExtendWith(MockitoExtension::class) class RegisterLocalActorApplicationServiceTest { @@ -51,7 +51,7 @@ class RegisterLocalActorApplicationServiceTest { val transaction = TestTransaction @Spy - val applicationConfig = ApplicationConfig(URL("http://example.com")) + val applicationConfig = ApplicationConfig(URI.create("http://example.com")) @Spy val idGenerateService = TwitterSnowflakeIdGenerateService diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/actor/RemoteActorCheckDomainServiceTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/actor/RemoteActorCheckDomainServiceTest.kt index 0b7acd6d..1eb4af84 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/actor/RemoteActorCheckDomainServiceTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/actor/RemoteActorCheckDomainServiceTest.kt @@ -15,7 +15,7 @@ class RemoteActorCheckDomainServiceTest { val remoteActor = RemoteActorCheckDomainService( ApplicationConfig( - URI.create("https://local.example.com").toURL() + URI.create("https://local.example.com") ) ).isRemoteActor( actor @@ -30,7 +30,7 @@ class RemoteActorCheckDomainServiceTest { val localActor = RemoteActorCheckDomainService( ApplicationConfig( - URI.create("https://local.example.com").toURL() + URI.create("https://local.example.com") ) ).isRemoteActor( actor diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/actor/local/LocalActorDomainServiceImplTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/actor/local/LocalActorDomainServiceImplTest.kt index a5fcf1a1..4116b0e2 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/actor/local/LocalActorDomainServiceImplTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/domain/service/actor/local/LocalActorDomainServiceImplTest.kt @@ -15,7 +15,7 @@ import org.mockito.junit.jupiter.MockitoExtension import org.mockito.kotlin.doReturn import org.mockito.kotlin.eq import org.mockito.kotlin.whenever -import java.net.URL +import java.net.URI @ExtendWith(MockitoExtension::class) class LocalActorDomainServiceImplTest { @@ -26,7 +26,7 @@ class LocalActorDomainServiceImplTest { lateinit var actorRepository: ActorRepository @Spy - val applicationConfig = ApplicationConfig(URL("http://example.com")) + val applicationConfig = ApplicationConfig(URI.create("http://example.com")) @Test fun findByNameAndDomainがnullならfalse() = runTest { diff --git a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImplTest.kt b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImplTest.kt index cf24d329..652de5f0 100644 --- a/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImplTest.kt +++ b/hideout-core/src/test/kotlin/dev/usbharu/hideout/core/infrastructure/springframework/oauth2/UserDetailsServiceImplTest.kt @@ -19,7 +19,7 @@ import org.mockito.junit.jupiter.MockitoExtension import org.mockito.kotlin.* import org.springframework.security.core.userdetails.UsernameNotFoundException import utils.TestTransaction -import java.net.URL +import java.net.URI import kotlin.test.assertEquals @ExtendWith(MockitoExtension::class) @@ -34,7 +34,7 @@ class UserDetailsServiceImplTest { lateinit var userDetailRepository: UserDetailRepository @Spy - val applicationConfig = ApplicationConfig(URL("http://example.com")) + val applicationConfig = ApplicationConfig(URI.create("http://example.com")) @Spy val transaction = TestTransaction From c3fdf98fd6b94fca08a0cf39ff04e2b0cc73bca4 Mon Sep 17 00:00:00 2001 From: usbharu Date: Sun, 22 Sep 2024 02:48:26 +0000 Subject: [PATCH 56/56] style: fix lint (CI) --- .../application/instance/GetLocalInstanceApplicationService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt index c8c1dbc7..0db792d1 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt @@ -46,7 +46,7 @@ class GetLocalInstanceApplicationService( } val instance = ( - instanceRepository.findByUrl(applicationConfig.url) + instanceRepository.findByUrl(applicationConfig.url) ?: throw InternalServerException("Local instance not found.") )