1 defmodule Pleroma.LoadTesting.Generator do
2 use Pleroma.LoadTesting.Helper
3 alias Pleroma.Web.CommonAPI
5 def generate_users(opts) do
6 IO.puts("Starting generating #{opts[:users_max]} users...")
7 {time, _} = :timer.tc(fn -> do_generate_users(opts) end)
9 IO.puts("Inserting users take #{to_sec(time)} sec.\n")
12 defp do_generate_users(opts) do
13 max = Keyword.get(opts, :users_max)
17 &generate_user_data(&1),
24 defp generate_user_data(i) do
25 remote = Enum.random([true, false])
28 name: "Test ใในใ User #{i}",
29 email: "user#{i}@example.com",
32 "$pbkdf2-sha512$160000$bU.OSFI7H/yqWb5DPEqyjw$uKp/2rmXw12QqnRRTqTtuk2DTwZfF8VR4MYW2xMeIlqPR/UX1nT1CEKVUx2CowFMZ5JON8aDvURrZpJjSgqXrg",
33 bio: "Tester Number #{i}",
41 Enum.random(["https://domain1.com", "https://domain2.com", "https://domain3.com"])
43 ap_id = "#{base_url}/users/#{user.nickname}"
47 follower_address: ap_id <> "/followers",
48 following_address: ap_id <> "/following"
52 ap_id: User.ap_id(user),
53 follower_address: User.ap_followers(user),
54 following_address: User.ap_following(user)
58 user = Map.merge(user, user_urls)
63 def generate_activities(user, users) do
64 do_generate_activities(user, users)
67 defp do_generate_activities(user, users) do
68 IO.puts("Starting generating 20000 common activities...")
75 do_generate_activity([user | users])
83 IO.puts("Inserting common activities take #{to_sec(time)} sec.\n")
85 IO.puts("Starting generating 20000 activities with mentions...")
92 do_generate_activity_with_mention(user, users)
100 IO.puts("Inserting activities with menthions take #{to_sec(time)} sec.\n")
102 IO.puts("Starting generating 10000 activities with threads...")
109 do_generate_threads([user | users])
117 IO.puts("Inserting activities with threads take #{to_sec(time)} sec.\n")
120 defp do_generate_activity(users) do
122 "status" => "Some status without mention with random user"
125 CommonAPI.post(Enum.random(users), post)
128 defp do_generate_activity_with_mention(user, users) do
129 mentions_cnt = Enum.random([2, 3, 4, 5])
130 with_user = Enum.random([true, false])
131 users = Enum.shuffle(users)
132 mentions_users = Enum.take(users, mentions_cnt)
133 mentions_users = if with_user, do: [user | mentions_users], else: mentions_users
136 Enum.map(mentions_users, fn user -> "@" <> user.nickname end) |> Enum.join(", ")
139 "status" => mentions_str <> "some status with mentions random users"
142 CommonAPI.post(Enum.random(users), post)
145 defp do_generate_threads(users) do
146 thread_length = Enum.random([2, 3, 4, 5])
147 actor = Enum.random(users)
150 "status" => "Start of the thread"
153 {:ok, activity} = CommonAPI.post(actor, post)
155 Enum.each(1..thread_length, fn _ ->
156 user = Enum.random(users)
159 "status" => "@#{actor.nickname} reply to thread",
160 "in_reply_to_status_id" => activity.id
163 CommonAPI.post(user, post)
167 def generate_remote_activities(user, users) do
168 do_generate_remote_activities(user, users)
171 defp do_generate_remote_activities(user, users) do
172 IO.puts("Starting generating 10000 remote activities...")
179 do_generate_remote_activity(i, user, users)
187 IO.puts("Inserting remote activities take #{to_sec(time)} sec.\n")
190 defp do_generate_remote_activity(i, user, users) do
191 actor = Enum.random(users)
192 %{host: host} = URI.parse(actor.ap_id)
193 date = Date.utc_today()
194 datetime = DateTime.utc_now()
197 "actor" => actor.ap_id,
198 "cc" => [actor.follower_address, user.ap_id],
199 "context" => "tag:mastodon.example.org,#{date}:objectId=#{i}:objectType=Conversation",
200 "id" => actor.ap_id <> "/statuses/#{i}/activity",
202 "actor" => actor.ap_id,
203 "atomUri" => actor.ap_id <> "/statuses/#{i}",
205 "attributedTo" => actor.ap_id,
208 "cc" => [actor.follower_address, user.ap_id],
210 "<p><span class=\"h-card\"><a href=\"" <>
212 "\" class=\"u-url mention\">@<span>" <> user.nickname <> "</span></a></span></p>",
213 "context" => "tag:mastodon.example.org,#{date}:objectId=#{i}:objectType=Conversation",
215 "tag:mastodon.example.org,#{date}:objectId=#{i}:objectType=Conversation",
217 "id" => actor.ap_id <> "/statuses/#{i}",
219 "inReplyToAtomUri" => nil,
220 "published" => datetime,
225 "href" => user.ap_id,
226 "name" => "@#{user.nickname}@#{host}",
230 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
232 "url" => "http://#{host}/@#{actor.nickname}/#{i}"
234 "published" => datetime,
235 "to" => ["https://www.w3.org/ns/activitystreams#Public"],
239 Pleroma.Web.ActivityPub.ActivityPub.insert(map, false)
242 def generate_dms(user, users, opts) do
243 IO.puts("Starting generating #{opts[:dms_max]} DMs")
244 {time, _} = :timer.tc(fn -> do_generate_dms(user, users, opts) end)
245 IO.puts("Inserting dms take #{to_sec(time)} sec.\n")
248 defp do_generate_dms(user, users, opts) do
252 do_generate_dm(user, users)
260 defp do_generate_dm(user, users) do
262 "status" => "@#{user.nickname} some direct message",
263 "visibility" => "direct"
266 CommonAPI.post(Enum.random(users), post)
269 def generate_long_thread(user, users, opts) do
270 IO.puts("Starting generating long thread with #{opts[:thread_length]} replies")
271 {time, activity} = :timer.tc(fn -> do_generate_long_thread(user, users, opts) end)
272 IO.puts("Inserting long thread replies take #{to_sec(time)} sec.\n")
276 defp do_generate_long_thread(user, users, opts) do
277 {:ok, %{id: id} = activity} = CommonAPI.post(user, %{"status" => "Start of long thread"})
280 1..opts[:thread_length],
281 fn _ -> do_generate_thread(users, id) end,
290 defp do_generate_thread(users, activity_id) do
291 CommonAPI.post(Enum.random(users), %{
292 "status" => "reply to main post",
293 "in_reply_to_status_id" => activity_id
297 def generate_non_visible_message(user, users) do
298 IO.puts("Starting generating 1000 non visible posts")
302 do_generate_non_visible_posts(user, users)
305 IO.puts("Inserting non visible posts take #{to_sec(time)} sec.\n")
308 defp do_generate_non_visible_posts(user, users) do
309 [not_friend | users] = users
311 make_friends(user, users)
313 Task.async_stream(1..1000, fn _ -> do_generate_non_visible_post(not_friend, users) end,
320 defp make_friends(_user, []), do: nil
322 defp make_friends(user, [friend | users]) do
323 {:ok, _} = User.follow(user, friend)
324 {:ok, _} = User.follow(friend, user)
325 make_friends(user, users)
328 defp do_generate_non_visible_post(not_friend, users) do
330 "status" => "some non visible post",
331 "visibility" => "private"
334 {:ok, activity} = CommonAPI.post(not_friend, post)
336 thread_length = Enum.random([2, 3, 4, 5])
338 Enum.each(1..thread_length, fn _ ->
339 user = Enum.random(users)
342 "status" => "@#{not_friend.nickname} reply to non visible post",
343 "in_reply_to_status_id" => activity.id,
344 "visibility" => "private"
347 CommonAPI.post(user, post)