Browse Source

test: Split Unit and Integration tests into separate projects (#1290)

* Squashed commit of test rewrite changes

fix missing priority speaker flag

rewrite the TestChannelPermissionModify test

add test for GuildPermission modify

separate unit and integration tests, start writing channel and guild permission tests

copy over the color tests

copy over the emote tests

copy the token utils tests

make the mocked entities sealed classes

copy the TypeReaderTests class

properly dispose the CommandService in the TypeReaderTests

start writing tests for EmbedBuilder and related classes

test that properties throw ArgumentException when invalid

add tests for the embed length property

add withFooter tests

finish adding tests to EmbedBuilder

fix bug in value validation of EmbedFieldBuilder

hey, these tests actually found a bug!

add tests for the MentionUtils class

add tests for the Format util class

remove all of the old tests

add analyzer tests (copied from old tests)

add tests for the SnowflakeUtils class

add integration tests

these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then

remove unnecessary launchSettings.json

update outdated string

don't create a new guild each time, as that can result in errors

this can happen if a bot creates too many guilds without properly deleting them

add some tests that show that guild can be modified

await async assert

add more measures that created channels are deleted when done

remove "Test" prefix from test method names

I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant

Remove mention of old test project

fix an issue from forgetting to await Assert.ThrowsAsync

explicitly disable parallelization on integration tests

add test for GuildPermission modify

separate unit and integration tests, start writing channel and guild permission tests

copy over the color tests

copy over the emote tests

make the mocked entities sealed classes

properly dispose the CommandService in the TypeReaderTests

fix bug in value validation of EmbedFieldBuilder

hey, these tests actually found a bug!

add tests for the MentionUtils class

add tests for the Format util class

remove all of the old tests

add analyzer tests (copied from old tests)

add tests for the SnowflakeUtils class

add integration tests

these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then

remove unnecessary launchSettings.json

update outdated string

don't create a new guild each time, as that can result in errors

this can happen if a bot creates too many guilds without properly deleting them

add more measures that created channels are deleted when done

remove "Test" prefix from test method names

I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant

Remove mention of old test project

fix an issue from forgetting to await Assert.ThrowsAsync

explicitly disable parallelization on integration tests

update the azure CI build script

separate execution of test projects so that if one fails the other will not pass

one of the unit tests failed, but the analzyer tests passed

fix test that would break in different timezones

enable the integration tests (only on dev branch)

* Squashed commit of test rewrite changes

fix missing priority speaker flag

rewrite the TestChannelPermissionModify test

add test for GuildPermission modify

separate unit and integration tests, start writing channel and guild permission tests

copy over the color tests

copy over the emote tests

copy the token utils tests

make the mocked entities sealed classes

copy the TypeReaderTests class

properly dispose the CommandService in the TypeReaderTests

start writing tests for EmbedBuilder and related classes

test that properties throw ArgumentException when invalid

add tests for the embed length property

add withFooter tests

finish adding tests to EmbedBuilder

fix bug in value validation of EmbedFieldBuilder

hey, these tests actually found a bug!

add tests for the MentionUtils class

add tests for the Format util class

remove all of the old tests

add analyzer tests (copied from old tests)

add tests for the SnowflakeUtils class

add integration tests

these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then

remove unnecessary launchSettings.json

update outdated string

don't create a new guild each time, as that can result in errors

this can happen if a bot creates too many guilds without properly deleting them

add some tests that show that guild can be modified

await async assert

add more measures that created channels are deleted when done

remove "Test" prefix from test method names

I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant

Remove mention of old test project

fix an issue from forgetting to await Assert.ThrowsAsync

explicitly disable parallelization on integration tests

add test for GuildPermission modify

separate unit and integration tests, start writing channel and guild permission tests

copy over the color tests

copy over the emote tests

make the mocked entities sealed classes

properly dispose the CommandService in the TypeReaderTests

fix bug in value validation of EmbedFieldBuilder

hey, these tests actually found a bug!

add tests for the MentionUtils class

add tests for the Format util class

remove all of the old tests

add analyzer tests (copied from old tests)

add tests for the SnowflakeUtils class

add integration tests

these get around the issue of state persisting between tests by creating and deleting a guild for each set of tests. these shouldn't be run excessively because of the rate limits, but should be fine every now and then

remove unnecessary launchSettings.json

update outdated string

don't create a new guild each time, as that can result in errors

this can happen if a bot creates too many guilds without properly deleting them

add more measures that created channels are deleted when done

remove "Test" prefix from test method names

I think that this prefix when already displayed under a class with a suffix of "Tests" is redundant

Remove mention of old test project

fix an issue from forgetting to await Assert.ThrowsAsync

explicitly disable parallelization on integration tests

update the azure CI build script

separate execution of test projects so that if one fails the other will not pass

one of the unit tests failed, but the analzyer tests passed

fix test that would break in different timezones

enable the integration tests (only on dev branch)

* Update mocked channels for changed SendFileAsync signature

* comment out the integration tests from the build script

no bot token is provided to this script, and use of integration tests in CI is questionable here

* force rebuild because Azure linux build broke
tags/2.2.0
Chris Johnston Christopher F 6 years ago
parent
commit
a797be9ca0
49 changed files with 2326 additions and 2349 deletions
  1. +44
    -43
      Discord.Net.sln
  2. +8
    -3
      azure/build.yml
  3. +2
    -2
      src/Discord.Net.Core/AssemblyInfo.cs
  4. +1
    -1
      src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs
  5. +24
    -0
      test/Discord.Net.Analyzers.Tests/Discord.Net.Analyzers.Tests.csproj
  6. +0
    -0
      test/Discord.Net.Analyzers.Tests/Extensions/AppDomainPolyfill.cs
  7. +0
    -0
      test/Discord.Net.Analyzers.Tests/GuildAccessTests.cs
  8. +0
    -0
      test/Discord.Net.Analyzers.Tests/Helpers/CodeFixVerifier.Helper.cs
  9. +0
    -0
      test/Discord.Net.Analyzers.Tests/Helpers/DiagnosticResult.cs
  10. +0
    -0
      test/Discord.Net.Analyzers.Tests/Helpers/DiagnosticVerifier.Helper.cs
  11. +0
    -0
      test/Discord.Net.Analyzers.Tests/Verifiers/CodeFixVerifier.cs
  12. +0
    -0
      test/Discord.Net.Analyzers.Tests/Verifiers/DiagnosticVerifier.cs
  13. +163
    -0
      test/Discord.Net.Tests.Integration/ChannelsTests.cs
  14. +27
    -0
      test/Discord.Net.Tests.Integration/Discord.Net.Tests.Integration.csproj
  15. +34
    -0
      test/Discord.Net.Tests.Integration/DiscordRestClientFixture.cs
  16. +114
    -0
      test/Discord.Net.Tests.Integration/GuildTests.cs
  17. +44
    -0
      test/Discord.Net.Tests.Integration/RestGuildFixture.cs
  18. +223
    -0
      test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs
  19. +5
    -0
      test/Discord.Net.Tests.Unit/ColorTests.cs
  20. +21
    -0
      test/Discord.Net.Tests.Unit/Discord.Net.Tests.Unit.csproj
  21. +467
    -0
      test/Discord.Net.Tests.Unit/EmbedBuilderTests.cs
  22. +2
    -0
      test/Discord.Net.Tests.Unit/EmoteTests.cs
  23. +32
    -0
      test/Discord.Net.Tests.Unit/FormatTests.cs
  24. +164
    -0
      test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs
  25. +128
    -0
      test/Discord.Net.Tests.Unit/MentionUtilsTests.cs
  26. +84
    -0
      test/Discord.Net.Tests.Unit/MockedEntities/MockedCategoryChannel.cs
  27. +96
    -0
      test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs
  28. +105
    -0
      test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs
  29. +29
    -0
      test/Discord.Net.Tests.Unit/MockedEntities/MockedInvalidChannel.cs
  30. +205
    -0
      test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs
  31. +126
    -0
      test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs
  32. +24
    -0
      test/Discord.Net.Tests.Unit/SnowflakeUtilsTests.cs
  33. +12
    -47
      test/Discord.Net.Tests.Unit/TokenUtilsTests.cs
  34. +142
    -0
      test/Discord.Net.Tests.Unit/TypeReaderTests.cs
  35. +0
    -35
      test/Discord.Net.Tests/Discord.Net.Tests.csproj
  36. +0
    -12
      test/Discord.Net.Tests/Net/CacheInfo.cs
  37. +0
    -123
      test/Discord.Net.Tests/Net/CachedRestClient.cs
  38. +0
    -128
      test/Discord.Net.Tests/Net/FilesystemProvider.cs
  39. +0
    -144
      test/Discord.Net.Tests/Net/HttpMixin.cs
  40. +0
    -33
      test/Discord.Net.Tests/TestConfig.cs
  41. +0
    -177
      test/Discord.Net.Tests/Tests.ChannelPermissions.cs
  42. +0
    -218
      test/Discord.Net.Tests/Tests.Channels.cs
  43. +0
    -342
      test/Discord.Net.Tests/Tests.Guilds.cs
  44. +0
    -73
      test/Discord.Net.Tests/Tests.Migrations.cs
  45. +0
    -772
      test/Discord.Net.Tests/Tests.Permissions.cs
  46. +0
    -133
      test/Discord.Net.Tests/Tests.TypeReaders.cs
  47. +0
    -55
      test/Discord.Net.Tests/Tests.cs
  48. +0
    -4
      test/Discord.Net.Tests/config.json.example
  49. +0
    -4
      test/Discord.Net.Tests/xunit.runner.json

+ 44
- 43
Discord.Net.sln View File

@@ -18,8 +18,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Providers.WS4Ne
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{CC3D4B1C-9DE0-448B-8AE7-F3F1F3EC5C3A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Tests", "test\Discord.Net.Tests\Discord.Net.Tests.csproj", "{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Webhook", "src\Discord.Net.Webhook\Discord.Net.Webhook.csproj", "{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Analyzers", "src\Discord.Net.Analyzers\Discord.Net.Analyzers.csproj", "{BBA8E7FB-C834-40DC-822F-B112CB7F0140}"
@@ -32,11 +30,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "02_commands_framework", "sa
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "03_sharded_client", "samples\03_sharded_client\03_sharded_client.csproj", "{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "04_webhook_client", "samples\04_webhook_client\04_webhook_client.csproj", "{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Tests.Unit", "test\Discord.Net.Tests.Unit\Discord.Net.Tests.Unit.csproj", "{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Tests.Integration", "test\Discord.Net.Tests.Integration\Discord.Net.Tests.Integration.csproj", "{E169E15A-E82C-45BF-8C24-C2CADB7093AA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{D1F0271E-0EE2-4B66-AC3D-9871B7E1C4CF}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C7CF5621-7D36-433B-B337-5A2E3C101A71}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Examples", "src\Discord.Net.Examples\Discord.Net.Examples.csproj", "{7EA96B2B-4D71-458D-9423-839362DC38BE}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Discord.Net.Analyzers.Tests", "test\Discord.Net.Analyzers.Tests\Discord.Net.Analyzers.Tests.csproj", "{FC67057C-E92F-4E1C-98BE-46F839C8AD71}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -108,18 +108,6 @@ Global
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}.Release|x64.Build.0 = Release|Any CPU
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}.Release|x86.ActiveCfg = Release|Any CPU
{6BDEEC08-417B-459F-9CA3-FF8BAB18CAC7}.Release|x86.Build.0 = Release|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Debug|x64.ActiveCfg = Debug|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Debug|x64.Build.0 = Debug|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Debug|x86.ActiveCfg = Debug|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Debug|x86.Build.0 = Debug|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Release|Any CPU.Build.0 = Release|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Release|x64.ActiveCfg = Release|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Release|x64.Build.0 = Release|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Release|x86.ActiveCfg = Release|Any CPU
{C38E5BC1-11CB-4101-8A38-5B40A1BC6433}.Release|x86.Build.0 = Release|Any CPU
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9AFAB80E-D2D3-4EDB-B58C-BACA78D1EA30}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -180,30 +168,42 @@ Global
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}.Release|x64.Build.0 = Release|Any CPU
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}.Release|x86.ActiveCfg = Release|Any CPU
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26}.Release|x86.Build.0 = Release|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Debug|x64.ActiveCfg = Debug|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Debug|x64.Build.0 = Debug|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Debug|x86.ActiveCfg = Debug|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Debug|x86.Build.0 = Debug|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Release|Any CPU.ActiveCfg = Release|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Release|Any CPU.Build.0 = Release|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Release|x64.ActiveCfg = Release|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Release|x64.Build.0 = Release|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Release|x86.ActiveCfg = Release|Any CPU
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562}.Release|x86.Build.0 = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|x64.ActiveCfg = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|x64.Build.0 = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|x86.ActiveCfg = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Debug|x86.Build.0 = Debug|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|Any CPU.Build.0 = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|x64.ActiveCfg = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|x64.Build.0 = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|x86.ActiveCfg = Release|Any CPU
{7EA96B2B-4D71-458D-9423-839362DC38BE}.Release|x86.Build.0 = Release|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x64.ActiveCfg = Debug|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x64.Build.0 = Debug|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x86.ActiveCfg = Debug|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Debug|x86.Build.0 = Debug|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|Any CPU.Build.0 = Release|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x64.ActiveCfg = Release|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x64.Build.0 = Release|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x86.ActiveCfg = Release|Any CPU
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4}.Release|x86.Build.0 = Release|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x64.ActiveCfg = Debug|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x64.Build.0 = Debug|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x86.ActiveCfg = Debug|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Debug|x86.Build.0 = Debug|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|Any CPU.Build.0 = Release|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x64.ActiveCfg = Release|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x64.Build.0 = Release|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x86.ActiveCfg = Release|Any CPU
{E169E15A-E82C-45BF-8C24-C2CADB7093AA}.Release|x86.Build.0 = Release|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x64.ActiveCfg = Debug|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x64.Build.0 = Debug|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x86.ActiveCfg = Debug|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Debug|x86.Build.0 = Debug|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|Any CPU.Build.0 = Release|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x64.ActiveCfg = Release|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x64.Build.0 = Release|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x86.ActiveCfg = Release|Any CPU
{FC67057C-E92F-4E1C-98BE-46F839C8AD71}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -218,8 +218,9 @@ Global
{F2FF84FB-F6AD-47E5-9EE5-18206CAE136E} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
{4E1F1F40-B1DD-40C9-A4B1-A2046A4C9C76} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
{9B4C4AFB-3D15-44C6-9E36-12ED625AAA26} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
{88B77A5B-0BC0-4E99-8FD9-D83F6999F562} = {BB59D5B5-E7B0-4BF4-8F82-D14431B2799B}
{7EA96B2B-4D71-458D-9423-839362DC38BE} = {D1F0271E-0EE2-4B66-AC3D-9871B7E1C4CF}
{DBF8B16E-5967-4480-8EDE-15D98A0DF0C4} = {C7CF5621-7D36-433B-B337-5A2E3C101A71}
{E169E15A-E82C-45BF-8C24-C2CADB7093AA} = {C7CF5621-7D36-433B-B337-5A2E3C101A71}
{FC67057C-E92F-4E1C-98BE-46F839C8AD71} = {C7CF5621-7D36-433B-B337-5A2E3C101A71}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D2404771-EEC8-45F2-9D71-F3373F6C1495}


+ 8
- 3
azure/build.yml View File

@@ -5,9 +5,14 @@ steps:
- script: dotnet build "Discord.Net.sln" --no-restore -v minimal -c $(buildConfiguration) /p:BuildNumber=$(buildNumber) /p:IsTagBuild=$(buildTag)
displayName: Build projects

- script: dotnet test "test/Discord.Net.Tests/Discord.Net.Tests.csproj" --no-restore --no-build -v minimal -c $(buildConfiguration) --logger trx
# TODO: update this to support multiple tests
displayName: Test projects
- script: dotnet test "test/Discord.Net.Tests.Unit/Discord.Net.Tests.Unit.csproj" --no-restore --no-build -v minimal -c $(buildConfiguration) --logger trx
displayName: Unit Tests

- script: dotnet test "test/Discord.Net.Analyzers.Tests/Discord.Net.Analyzers.Tests.csproj" --no-restore --no-build -v minimal -c $(buildConfiguration) --logger trx
displayName: Analyzer Tests

# - script: dotnet test "test/Discord.Net.Tests.Integration/Discord.Net.Tests.Integration.csproj" --no-restore --no-build -v minimal -c $(buildConfiguration) --logger trx
# condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/dev'))

- task: PublishTestResults@2
displayName: Publish test results


+ 2
- 2
src/Discord.Net.Core/AssemblyInfo.cs View File

@@ -1,4 +1,4 @@
using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Discord.Net.Relay")]
[assembly: InternalsVisibleTo("Discord.Net.Rest")]
@@ -6,4 +6,4 @@
[assembly: InternalsVisibleTo("Discord.Net.WebSocket")]
[assembly: InternalsVisibleTo("Discord.Net.Webhook")]
[assembly: InternalsVisibleTo("Discord.Net.Commands")]
[assembly: InternalsVisibleTo("Discord.Net.Tests")]
[assembly: InternalsVisibleTo("Discord.Net.Tests.Unit")]

+ 1
- 1
src/Discord.Net.Core/Entities/Messages/EmbedBuilder.cs View File

@@ -486,7 +486,7 @@ namespace Discord
set
{
var stringValue = value?.ToString();
if (string.IsNullOrEmpty(stringValue)) throw new ArgumentException(message: "Field value must not be null or empty.", paramName: nameof(Value));
if (string.IsNullOrWhiteSpace(stringValue)) throw new ArgumentException(message: "Field value must not be null or empty.", paramName: nameof(Value));
if (stringValue.Length > MaxFieldValueLength) throw new ArgumentException(message: $"Field value length must be less than or equal to {MaxFieldValueLength}.", paramName: nameof(Value));
_value = stringValue;
}


+ 24
- 0
test/Discord.Net.Analyzers.Tests/Discord.Net.Analyzers.Tests.csproj View File

@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../../src/Discord.Net.Commands/Discord.Net.Commands.csproj" />
<ProjectReference Include="../../src/Discord.Net.Core/Discord.Net.Core.csproj" />
<ProjectReference Include="../../src/Discord.Net.Rest/Discord.Net.Rest.csproj" />
<ProjectReference Include="../../src/Discord.Net.Analyzers/Discord.Net.Analyzers.csproj" />
<ProjectReference Include="..\..\src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.0.0-beta4-final" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>

</Project>

test/Discord.Net.Tests/AnalyzerTests/Extensions/AppDomainPolyfill.cs → test/Discord.Net.Analyzers.Tests/Extensions/AppDomainPolyfill.cs View File


test/Discord.Net.Tests/AnalyzerTests/GuildAccessTests.cs → test/Discord.Net.Analyzers.Tests/GuildAccessTests.cs View File


test/Discord.Net.Tests/AnalyzerTests/Helpers/CodeFixVerifier.Helper.cs → test/Discord.Net.Analyzers.Tests/Helpers/CodeFixVerifier.Helper.cs View File


test/Discord.Net.Tests/AnalyzerTests/Helpers/DiagnosticResult.cs → test/Discord.Net.Analyzers.Tests/Helpers/DiagnosticResult.cs View File


test/Discord.Net.Tests/AnalyzerTests/Helpers/DiagnosticVerifier.Helper.cs → test/Discord.Net.Analyzers.Tests/Helpers/DiagnosticVerifier.Helper.cs View File


test/Discord.Net.Tests/AnalyzerTests/Verifiers/CodeFixVerifier.cs → test/Discord.Net.Analyzers.Tests/Verifiers/CodeFixVerifier.cs View File


test/Discord.Net.Tests/AnalyzerTests/Verifiers/DiagnosticVerifier.cs → test/Discord.Net.Analyzers.Tests/Verifiers/DiagnosticVerifier.cs View File


+ 163
- 0
test/Discord.Net.Tests.Integration/ChannelsTests.cs View File

@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

namespace Discord
{
/// <summary>
/// Tests that channels can be created and modified.
/// </summary>
[CollectionDefinition("ChannelsTests", DisableParallelization = true)]
public class ChannelsTests : IClassFixture<RestGuildFixture>
{
private IGuild guild;
private readonly ITestOutputHelper output;

public ChannelsTests(RestGuildFixture guildFixture, ITestOutputHelper output)
{
guild = guildFixture.Guild;
this.output = output;
output.WriteLine($"RestGuildFixture using guild: {guild.Id}");
// capture all console output
guildFixture.Client.Log += LogAsync;
}
private Task LogAsync(LogMessage message)
{
output.WriteLine(message.ToString());
return Task.CompletedTask;
}

/// <summary>
/// Checks that a text channel can be created and modified.
/// </summary>
[Fact]
public async Task ModifyTextChannel()
{
// create a text channel to modify
var channel = await guild.CreateTextChannelAsync("text");
try
{
Assert.NotNull(channel);
// check that it can be modified
await channel.ModifyAsync(x =>
{
x.IsNsfw = true;
x.Name = "updated";
x.SlowModeInterval = 50;
x.Topic = "topic";
x.CategoryId = null;
});
// check the results of modifying this channel
Assert.True(channel.IsNsfw);
Assert.Equal("updated", channel.Name);
Assert.Equal(50, channel.SlowModeInterval);
Assert.Equal("topic", channel.Topic);
Assert.Null(channel.CategoryId);
}
finally
{
// delete the channel when finished
await channel?.DeleteAsync();
}
}

/// <summary>
/// Checks that a voice channel can be created, modified, and deleted.
/// </summary>
[Fact]
public async Task ModifyVoiceChannel()
{
var channel = await guild.CreateVoiceChannelAsync("voice");
try
{
Assert.NotNull(channel);
// try to modify it
await channel.ModifyAsync(x =>
{
x.Bitrate = 9001;
x.Name = "updated";
x.UserLimit = 1;
});
// check that these were updated
Assert.Equal(9001, channel.Bitrate);
Assert.Equal("updated", channel.Name);
Assert.Equal(1, channel.UserLimit);
}
finally
{
// delete the channel when done
await channel.DeleteAsync();
}
}

/// <summary>
/// Creates a category channel, a voice channel, and a text channel, then tries to assign them under that category.
/// </summary>
[Fact]
public async Task ModifyChannelCategories()
{
// util method for checking if a category is set
async Task CheckAsync(INestedChannel channel, ICategoryChannel cat)
{
// check that the category is not set
if (cat == null)
{
Assert.Null(channel.CategoryId);
Assert.Null(await channel.GetCategoryAsync());
}
else
{
Assert.NotNull(channel.CategoryId);
Assert.Equal(cat.Id, channel.CategoryId);
var getCat = await channel.GetCategoryAsync();
Assert.NotNull(getCat);
Assert.Equal(cat.Id, getCat.Id);
}
}
// initially create these not under the category
var category = await guild.CreateCategoryAsync("category");
var text = await guild.CreateTextChannelAsync("text");
var voice = await guild.CreateVoiceChannelAsync("voice");

try
{
Assert.NotNull(category);
Assert.NotNull(text);
Assert.NotNull(voice);
// check that the category is not set for either
await CheckAsync(text, null);
await CheckAsync(voice, null);

// set the category
await text.ModifyAsync(x => x.CategoryId = category.Id);
await voice.ModifyAsync(x => x.CategoryId = category.Id);

// check that this is set, and that it's the category that was created earlier
await CheckAsync(text, category);
await CheckAsync(voice, category);

// create one more channel immediately under this category
var newText = await guild.CreateTextChannelAsync("new-text", x => x.CategoryId = category.Id);
try
{
Assert.NotNull(newText);
await CheckAsync(newText, category);
}
finally
{
await newText?.DeleteAsync();
}
}
finally
{
// clean up
await category?.DeleteAsync();
await text?.DeleteAsync();
await voice?.DeleteAsync();
}
}
}
}

+ 27
- 0
test/Discord.Net.Tests.Integration/Discord.Net.Tests.Integration.csproj View File

@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../../src/Discord.Net.Commands/Discord.Net.Commands.csproj" />
<ProjectReference Include="../../src/Discord.Net.Core/Discord.Net.Core.csproj" />
<ProjectReference Include="../../src/Discord.Net.Rest/Discord.Net.Rest.csproj" />
<ProjectReference Include="../../src/Discord.Net.Analyzers/Discord.Net.Analyzers.csproj" />
<ProjectReference Include="..\..\src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>

<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>

</Project>

+ 34
- 0
test/Discord.Net.Tests.Integration/DiscordRestClientFixture.cs View File

@@ -0,0 +1,34 @@
using Discord.Rest;
using System;
using Xunit;

namespace Discord
{
/// <summary>
/// Test fixture type for integration tests which sets up the client from
/// the token provided in environment variables.
/// </summary>
public class DiscordRestClientFixture : IDisposable
{
public DiscordRestClient Client { get; private set; }

public DiscordRestClientFixture()
{
var token = Environment.GetEnvironmentVariable("DNET_TEST_TOKEN", EnvironmentVariableTarget.Machine);
if (string.IsNullOrWhiteSpace(token))
throw new Exception("The DNET_TEST_TOKEN environment variable was not provided.");
Client = new DiscordRestClient(new DiscordRestConfig()
{
LogLevel = LogSeverity.Debug,
DefaultRetryMode = RetryMode.AlwaysRetry
});
Client.LoginAsync(TokenType.Bot, token).Wait();
}

public void Dispose()
{
Client.LogoutAsync().Wait();
Client.Dispose();
}
}
}

+ 114
- 0
test/Discord.Net.Tests.Integration/GuildTests.cs View File

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

namespace Discord
{
[CollectionDefinition("GuildTests", DisableParallelization = true)]
public class GuildTests : IClassFixture<RestGuildFixture>
{
private IDiscordClient client;
private IGuild guild;
private readonly ITestOutputHelper output;

public GuildTests(RestGuildFixture guildFixture, ITestOutputHelper output)
{
client = guildFixture.Client;
guild = guildFixture.Guild;
this.output = output;
output.WriteLine($"RestGuildFixture using guild: {guild.Id}");
guildFixture.Client.Log += LogAsync;
}
private Task LogAsync(LogMessage message)
{
output.WriteLine(message.ToString());
return Task.CompletedTask;
}
/// <summary>
/// Ensures that the CurrentUser is the owner of the guild.
/// </summary>
[Fact]
public void CheckOwner()
{
Assert.Equal(client.CurrentUser.Id, guild.OwnerId);
}
/// <summary>
/// Checks that a Guild can be modified to non-default values.
/// </summary>
[Fact]
public async Task ModifyGuild()
{
// set some initial properties of the guild that are not the defaults
await guild.ModifyAsync(x =>
{
x.ExplicitContentFilter = ExplicitContentFilterLevel.AllMembers;
x.Name = "updated";
x.DefaultMessageNotifications = DefaultMessageNotifications.MentionsOnly;
x.AfkTimeout = 900; // 15 minutes
x.VerificationLevel = VerificationLevel.None;
});
// check that they were set
Assert.Equal("updated", guild.Name);
Assert.Equal(ExplicitContentFilterLevel.AllMembers, guild.ExplicitContentFilter);
Assert.Equal(DefaultMessageNotifications.MentionsOnly, guild.DefaultMessageNotifications);
Assert.Equal(VerificationLevel.None, guild.VerificationLevel);
Assert.Equal(900, guild.AFKTimeout);
}
/// <summary>
/// Checks that the SystemChannel property of a guild can be modified.
/// </summary>
[Fact]
public async Task ModifySystemChannel()
{
var systemChannel = await guild.CreateTextChannelAsync("system");
// set using the Id
await guild.ModifyAsync(x => x.SystemChannelId = systemChannel.Id);
Assert.Equal(systemChannel.Id, guild.SystemChannelId);
// unset it
await guild.ModifyAsync(x => x.SystemChannelId = null);
Assert.Null(guild.SystemChannelId);
Assert.Null(await guild.GetSystemChannelAsync());

// set using the ITextChannel
await guild.ModifyAsync(x => { x.SystemChannel = new Optional<ITextChannel>(systemChannel); });
Assert.Equal(systemChannel.Id, guild.SystemChannelId);

await Assert.ThrowsAsync<NullReferenceException>( async () =>
{
await guild.ModifyAsync(x => x.SystemChannel = null);
});

await systemChannel.DeleteAsync();
}
/// <summary>
/// Checks that the AFK channel of a guild can be set.
/// </summary>
[Fact]
public async Task ModifyAfkChannel()
{
var afkChannel = await guild.CreateVoiceChannelAsync("afk");
// set using the Id
await guild.ModifyAsync(x => x.AfkChannelId = afkChannel.Id);
Assert.Equal(afkChannel.Id, guild.AFKChannelId);

// unset using Id
await guild.ModifyAsync(x => x.AfkChannelId = null);
Assert.Null(guild.AFKChannelId);
Assert.Null(await guild.GetAFKChannelAsync());

// the same, but with the AfkChannel property
await guild.ModifyAsync(x => x.AfkChannel = new Optional<IVoiceChannel>(afkChannel));
Assert.Equal(afkChannel.Id, guild.AFKChannelId);

await Assert.ThrowsAsync<NullReferenceException>( async () =>
{
await guild.ModifyAsync(x => x.AfkChannel = null);
});

await afkChannel.DeleteAsync();
}
}
}

+ 44
- 0
test/Discord.Net.Tests.Integration/RestGuildFixture.cs View File

@@ -0,0 +1,44 @@
using Discord.Rest;
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;

namespace Discord
{
/// <summary>
/// Gets or creates a guild to use for testing.
/// </summary>
public class RestGuildFixture : DiscordRestClientFixture
{
public RestGuild Guild { get; private set; }

public RestGuildFixture() : base()
{
var guilds = Client.GetGuildsAsync().Result.Where(x => x.OwnerId == Client.CurrentUser.Id).ToList();
if (guilds.Count == 0)
{
// create a new guild if none exists already
var region = Client.GetOptimalVoiceRegionAsync().Result;
Guild = Client.CreateGuildAsync("DNET INTEGRATION TEST", region).Result;
RemoveAllChannels();
}
else
{
// get the first one if there is a guild already created
Guild = guilds.First();
}
}

/// <summary>
/// Removes all channels in the guild.
/// </summary>
private void RemoveAllChannels()
{
foreach (var channel in Guild.GetChannelsAsync().Result)
{
channel.DeleteAsync().Wait();
}
}
}
}

+ 223
- 0
test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs View File

@@ -0,0 +1,223 @@
using System;
using System.Collections.Generic;
using Xunit;

namespace Discord
{
/// <summary>
/// Tests the behavior of the <see cref="Discord.ChannelPermissions"/> type and related functions.
/// </summary>
public class ChannelPermissionsTests
{
/// <summary>
/// Tests the default value of the <see cref="Discord.ChannelPermissions"/> constructor.
/// </summary>
[Fact]
public void DefaultConstructor()
{
var permission = new ChannelPermissions();
Assert.Equal((ulong)0, permission.RawValue);
Assert.Equal(ChannelPermissions.None.RawValue, permission.RawValue);
}

/// <summary>
/// Tests the behavior of the <see cref="Discord.ChannelPermission"/> raw value constructor.
/// </summary>
[Fact]
public void RawValueConstructor()
{
// returns all of the values that will be tested
// a Theory cannot be used here, because these values are not all constants
IEnumerable<ulong> GetTestValues()
{
yield return 0;
yield return ChannelPermissions.Category.RawValue;
yield return ChannelPermissions.DM.RawValue;
yield return ChannelPermissions.Group.RawValue;
yield return ChannelPermissions.None.RawValue;
yield return ChannelPermissions.Text.RawValue;
yield return ChannelPermissions.Voice.RawValue;
};

foreach (var rawValue in GetTestValues())
{
var p = new ChannelPermissions(rawValue);
Assert.Equal(rawValue, p.RawValue);
}
}

/// <summary>
/// Tests the behavior of the <see cref="Discord.ChannelPermissions"/> constructor for each
/// of it's flags.
/// </summary>
[Fact]
public void FlagsConstructor()
{
// util method for asserting that the constructor sets the given flag
void AssertFlag(Func<ChannelPermissions> cstr, ChannelPermission flag)
{
var p = cstr();
// ensure that this flag is set to true
Assert.True(p.Has(flag));
// ensure that only this flag is set
Assert.Equal((ulong)flag, p.RawValue);
}

AssertFlag(() => new ChannelPermissions(createInstantInvite: true), ChannelPermission.CreateInstantInvite);
AssertFlag(() => new ChannelPermissions(manageChannel: true), ChannelPermission.ManageChannels);
AssertFlag(() => new ChannelPermissions(addReactions: true), ChannelPermission.AddReactions);
AssertFlag(() => new ChannelPermissions(viewChannel: true), ChannelPermission.ViewChannel);
AssertFlag(() => new ChannelPermissions(sendMessages: true), ChannelPermission.SendMessages);
AssertFlag(() => new ChannelPermissions(sendTTSMessages: true), ChannelPermission.SendTTSMessages);
AssertFlag(() => new ChannelPermissions(manageMessages: true), ChannelPermission.ManageMessages);
AssertFlag(() => new ChannelPermissions(embedLinks: true), ChannelPermission.EmbedLinks);
AssertFlag(() => new ChannelPermissions(attachFiles: true), ChannelPermission.AttachFiles);
AssertFlag(() => new ChannelPermissions(readMessageHistory: true), ChannelPermission.ReadMessageHistory);
AssertFlag(() => new ChannelPermissions(mentionEveryone: true), ChannelPermission.MentionEveryone);
AssertFlag(() => new ChannelPermissions(useExternalEmojis: true), ChannelPermission.UseExternalEmojis);
AssertFlag(() => new ChannelPermissions(connect: true), ChannelPermission.Connect);
AssertFlag(() => new ChannelPermissions(speak: true), ChannelPermission.Speak);
AssertFlag(() => new ChannelPermissions(muteMembers: true), ChannelPermission.MuteMembers);
AssertFlag(() => new ChannelPermissions(deafenMembers: true), ChannelPermission.DeafenMembers);
AssertFlag(() => new ChannelPermissions(moveMembers: true), ChannelPermission.MoveMembers);
AssertFlag(() => new ChannelPermissions(useVoiceActivation: true), ChannelPermission.UseVAD);
AssertFlag(() => new ChannelPermissions(prioritySpeaker: true), ChannelPermission.PrioritySpeaker);
AssertFlag(() => new ChannelPermissions(manageRoles: true), ChannelPermission.ManageRoles);
AssertFlag(() => new ChannelPermissions(manageWebhooks: true), ChannelPermission.ManageWebhooks);
}

/// <summary>
/// Tests the behavior of <see cref="Discord.ChannelPermissions.Modify(bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?)"/>
/// with each of the parameters.
/// </summary>
[Fact]
public void Modify()
{
// asserts that a channel permission flag value can be checked
// and that modify can set and unset each flag
// and that ToList performs as expected
void AssertUtil(ChannelPermission permission,
Func<ChannelPermissions, bool> has,
Func<ChannelPermissions, bool, ChannelPermissions> modify)
{
var perm = new ChannelPermissions();
// ensure permission initially false
// use both the function and Has to ensure that the GetPermission
// function is working
Assert.False(has(perm));
Assert.False(perm.Has(permission));

// enable it, and ensure that it gets set
perm = modify(perm, true);
Assert.True(has(perm));
Assert.True(perm.Has(permission));

// check ToList behavior
var list = perm.ToList();
Assert.Contains(permission, list);
Assert.Single(list);

// set it false again
perm = modify(perm, false);
Assert.False(has(perm));
Assert.False(perm.Has(permission));

// ensure that no perms are set now
Assert.Equal(ChannelPermissions.None.RawValue, perm.RawValue);
}

AssertUtil(ChannelPermission.CreateInstantInvite, x => x.CreateInstantInvite, (p, enable) => p.Modify(createInstantInvite: enable));
AssertUtil(ChannelPermission.ManageChannels, x => x.ManageChannel, (p, enable) => p.Modify(manageChannel: enable));
AssertUtil(ChannelPermission.AddReactions, x => x.AddReactions, (p, enable) => p.Modify(addReactions: enable));
AssertUtil(ChannelPermission.ViewChannel, x => x.ViewChannel, (p, enable) => p.Modify(viewChannel: enable));
AssertUtil(ChannelPermission.SendMessages, x => x.SendMessages, (p, enable) => p.Modify(sendMessages: enable));
AssertUtil(ChannelPermission.SendTTSMessages, x => x.SendTTSMessages, (p, enable) => p.Modify(sendTTSMessages: enable));
AssertUtil(ChannelPermission.ManageMessages, x => x.ManageMessages, (p, enable) => p.Modify(manageMessages: enable));
AssertUtil(ChannelPermission.EmbedLinks, x => x.EmbedLinks, (p, enable) => p.Modify(embedLinks: enable));
AssertUtil(ChannelPermission.AttachFiles, x => x.AttachFiles, (p, enable) => p.Modify(attachFiles: enable));
AssertUtil(ChannelPermission.ReadMessageHistory, x => x.ReadMessageHistory, (p, enable) => p.Modify(readMessageHistory: enable));
AssertUtil(ChannelPermission.MentionEveryone, x => x.MentionEveryone, (p, enable) => p.Modify(mentionEveryone: enable));
AssertUtil(ChannelPermission.UseExternalEmojis, x => x.UseExternalEmojis, (p, enable) => p.Modify(useExternalEmojis: enable));
AssertUtil(ChannelPermission.Connect, x => x.Connect, (p, enable) => p.Modify(connect: enable));
AssertUtil(ChannelPermission.Speak, x => x.Speak, (p, enable) => p.Modify(speak: enable));
AssertUtil(ChannelPermission.MuteMembers, x => x.MuteMembers, (p, enable) => p.Modify(muteMembers: enable));
AssertUtil(ChannelPermission.DeafenMembers, x => x.DeafenMembers, (p, enable) => p.Modify(deafenMembers: enable));
AssertUtil(ChannelPermission.MoveMembers, x => x.MoveMembers, (p, enable) => p.Modify(moveMembers: enable));
AssertUtil(ChannelPermission.UseVAD, x => x.UseVAD, (p, enable) => p.Modify(useVoiceActivation: enable));
AssertUtil(ChannelPermission.ManageRoles, x => x.ManageRoles, (p, enable) => p.Modify(manageRoles: enable));
AssertUtil(ChannelPermission.ManageWebhooks, x => x.ManageWebhooks, (p, enable) => p.Modify(manageWebhooks: enable));
AssertUtil(ChannelPermission.PrioritySpeaker, x => x.PrioritySpeaker, (p, enable) => p.Modify(prioritySpeaker: enable));
}

/// <summary>
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for a null channel will throw an <see cref="ArgumentException"/>.
/// </summary>
[Fact]
public void ChannelTypeResolution_Null()
{
Assert.Throws<ArgumentException>(() =>
{
ChannelPermissions.All(null);
});
}

/// <summary>
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="ITextChannel"/> will return a value
/// equivalent to <see cref="ChannelPermissions.Text"/>.
/// </summary>
[Fact]
public void ChannelTypeResolution_Text()
{
Assert.Equal(ChannelPermissions.Text.RawValue, ChannelPermissions.All(new MockedTextChannel()).RawValue);
}

/// <summary>
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="IVoiceChannel"/> will return a value
/// equivalent to <see cref="ChannelPermissions.Voice"/>.
/// </summary>
[Fact]
public void ChannelTypeResolution_Voice()
{
Assert.Equal(ChannelPermissions.Voice.RawValue, ChannelPermissions.All(new MockedVoiceChannel()).RawValue);
}

/// <summary>
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="ICategoryChannel"/> will return a value
/// equivalent to <see cref="ChannelPermissions.Category"/>.
/// </summary>
[Fact]
public void ChannelTypeResolution_Category()
{
Assert.Equal(ChannelPermissions.Category.RawValue, ChannelPermissions.All(new MockedCategoryChannel()).RawValue);
}

/// <summary>
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="IDMChannel"/> will return a value
/// equivalent to <see cref="ChannelPermissions.DM"/>.
/// </summary>
[Fact]
public void ChannelTypeResolution_DM()
{
Assert.Equal(ChannelPermissions.DM.RawValue, ChannelPermissions.All(new MockedDMChannel()).RawValue);
}

/// <summary>
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an <see cref="IGroupChannel"/> will return a value
/// equivalent to <see cref="ChannelPermissions.Group"/>.
/// </summary>
[Fact]
public void ChannelTypeResolution_Group()
{
Assert.Equal(ChannelPermissions.Group.RawValue, ChannelPermissions.All(new MockedGroupChannel()).RawValue);
}

/// <summary>
/// Tests that <see cref="ChannelPermissions.All(IChannel)"/> for an invalid channel will throw an <see cref="ArgumentException"/>.
/// </summary>
[Fact]
public void ChannelTypeResolution_Invalid()
{
Assert.Throws<ArgumentException>(() => ChannelPermissions.All(new MockedInvalidChannel()));
}
}
}

test/Discord.Net.Tests/Tests.Colors.cs → test/Discord.Net.Tests.Unit/ColorTests.cs View File

@@ -1,8 +1,13 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Discord
{
/// <summary>
/// Tests for the <see cref="Discord.Color"/> type.
/// </summary>
public class ColorTests
{
[Fact]

+ 21
- 0
test/Discord.Net.Tests.Unit/Discord.Net.Tests.Unit.csproj View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../../src/Discord.Net.Commands/Discord.Net.Commands.csproj" />
<ProjectReference Include="../../src/Discord.Net.Core/Discord.Net.Core.csproj" />
<ProjectReference Include="../../src/Discord.Net.Rest/Discord.Net.Rest.csproj" />
<ProjectReference Include="../../src/Discord.Net.Analyzers/Discord.Net.Analyzers.csproj" />
<ProjectReference Include="..\..\src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
</ItemGroup>

</Project>

+ 467
- 0
test/Discord.Net.Tests.Unit/EmbedBuilderTests.cs View File

@@ -0,0 +1,467 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Discord
{
/// <summary>
/// Tests the <see cref="Discord.EmbedBuilder"/> class.
/// </summary>
public class EmbedBuilderTests
{
private const string name = "chrisj";
private const string icon = "https://meowpuffygottem.fun/blob.png";
private const string url = "https://meowpuffygottem.fun/";

/// <summary>
/// Tests the behavior of <see cref="EmbedBuilder.WithAuthor(string, string, string)"/>.
/// </summary>
[Fact]
public void WithAuthor_Strings()
{
var builder = new EmbedBuilder();
// null by default
Assert.Null(builder.Author);

builder = new EmbedBuilder()
.WithAuthor(name, icon, url);

Assert.NotNull(builder.Author);
Assert.Equal(name, builder.Author.Name);
Assert.Equal(icon, builder.Author.IconUrl);
Assert.Equal(url, builder.Author.Url);
}

/// <summary>
/// Tests the behavior of <see cref="EmbedBuilder.WithAuthor(EmbedAuthorBuilder)"/>
/// </summary>
[Fact]
public void WithAuthor_AuthorBuilder()
{
var author = new EmbedAuthorBuilder()
.WithIconUrl(icon)
.WithName(name)
.WithUrl(url);
var builder = new EmbedBuilder()
.WithAuthor(author);
Assert.NotNull(builder.Author);
Assert.Equal(name, builder.Author.Name);
Assert.Equal(icon, builder.Author.IconUrl);
Assert.Equal(url, builder.Author.Url);
}

/// <summary>
/// Tests the behavior of <see cref="EmbedBuilder.WithAuthor(Action{EmbedAuthorBuilder})"/>
/// </summary>
[Fact]
public void WithAuthor_ActionAuthorBuilder()
{
var builder = new EmbedBuilder()
.WithAuthor((author) =>
author.WithIconUrl(icon)
.WithName(name)
.WithUrl(url));
Assert.NotNull(builder.Author);
Assert.Equal(name, builder.Author.Name);
Assert.Equal(icon, builder.Author.IconUrl);
Assert.Equal(url, builder.Author.Url);
}

/// <summary>
/// Tests the behavior of <see cref="EmbedAuthorBuilder"/>.
/// </summary>
[Fact]
public void EmbedAuthorBuilder()
{
var builder = new EmbedAuthorBuilder()
.WithIconUrl(icon)
.WithName(name)
.WithUrl(url);
Assert.Equal(icon, builder.IconUrl);
Assert.Equal(name, builder.Name);
Assert.Equal(url, builder.Url);
}

/// <summary>
/// Tests that invalid titles throw an <see cref="ArgumentException"/>.
/// </summary>
/// <param name="title">The embed title to set.</param>
[Theory]
// 257 chars
[InlineData("jVyLChmA7aBZozXQuZ3VDEcwW6zOq0nteOVYBZi31ny73rpXfSSBXR4Jw6FiplDKQseKskwRMuBZkUewrewqAbkBZpslHirvC5nEzRySoDIdTRnkVvTXZUXg75l3bQCjuuHxDd6DfrY8ihd6yZX1Y0XFeg239YBcYV4TpL9uQ8H3HFYxrWhLlG2PRVjUmiglP5iXkawszNwMVm1SZ5LZT4jkMZHxFegVi7170d16iaPWOovu50aDDHy087XBtLKVa")]
// 257 chars of whitespace
[InlineData(" ")]
public void Title_Invalid(string title)
{
Assert.Throws<ArgumentException>(() =>
{
var builder = new EmbedBuilder();
builder.Title = title;
});
Assert.Throws<ArgumentException>(() =>
{
new EmbedBuilder().WithTitle(title);
});
}

/// <summary>
/// Tests that valid titles do not throw any exceptions.
/// </summary>
/// <param name="title">The embed title to set.</param>
[Theory]
// 256 chars
[InlineData("jVyLChmA7aBZozXQuZ3VDEcwW6zOq0nteOVYBZi31ny73rpXfSSBXR4Jw6FiplDKQseKskwRMuBZkUewrewqAbkBZpslHirvC5nEzRySoDIdTRnkVvTXZUXg75l3bQCjuuHxDd6DfrY8ihd6yZX1Y0XFeg239YBcYV4TpL9uQ8H3HFYxrWhLlG2PRVjUmiglP5iXkawszNwMVm1SZ5LZT4jkMZHxFegVi7170d16iaPWOovu50aDDHy087XBtLKV")]
public void Tile_Valid(string title)
{
var builder = new EmbedBuilder();
builder.Title = title;
new EmbedBuilder().WithTitle(title);
}

/// <summary>
/// Tests that invalid descriptions throw an <see cref="ArgumentException"/>.
/// </summary>
[Fact]
public void Description_Invalid()
{
IEnumerable<string> GetInvalid()
{
yield return new string('a', 2049);
}
foreach (var description in GetInvalid())
{
Assert.Throws<ArgumentException>(() => new EmbedBuilder().WithDescription(description));
Assert.Throws<ArgumentException>(() =>
{
var b = new EmbedBuilder();
b.Description = description;
});
}
}

/// <summary>
/// Tests that valid descriptions do not throw any exceptions.
/// </summary>
[Fact]
public void Description_Valid()
{
IEnumerable<string> GetValid()
{
yield return string.Empty;
yield return null;
yield return new string('a', 2048);
}
foreach (var description in GetValid())
{
var b = new EmbedBuilder().WithDescription(description);
Assert.Equal(description, b.Description);

b = new EmbedBuilder();
b.Description = description;
Assert.Equal(description, b.Description);
}
}

/// <summary>
/// Tests that valid urls do not throw any exceptions.
/// </summary>
/// <param name="url">The url to set.</param>
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("https://docs.stillu.cc")]
public void Url_Valid(string url)
{
// does not throw an exception
var result = new EmbedBuilder()
.WithUrl(url)
.WithImageUrl(url)
.WithThumbnailUrl(url);
Assert.Equal(result.Url, url);
Assert.Equal(result.ImageUrl, url);
Assert.Equal(result.ThumbnailUrl, url);

result = new EmbedBuilder();
result.Url = url;
result.ImageUrl = url;
result.ThumbnailUrl = url;
Assert.Equal(result.Url, url);
Assert.Equal(result.ImageUrl, url);
Assert.Equal(result.ThumbnailUrl, url);
}

/// <summary>
/// Tests that invalid urls throw an <see cref="ArgumentException"/>.
/// </summary>
/// <param name="url">The url to set.</param>
[Theory]
[InlineData(" ")]
[InlineData("not a url")]
public void Url_Invalid(string url)
{
Assert.Throws<ArgumentException>(()
=> new EmbedBuilder()
.WithUrl(url));
Assert.Throws<ArgumentException>(()
=> new EmbedBuilder()
.WithImageUrl(url));
Assert.Throws<ArgumentException>(()
=> new EmbedBuilder()
.WithThumbnailUrl(url));

Assert.Throws<ArgumentException>(() =>
{
var b = new EmbedBuilder();
b.Url = url;
});
Assert.Throws<ArgumentException>(() =>
{
var b = new EmbedBuilder();
b.ImageUrl = url;
});
Assert.Throws<ArgumentException>(() =>
{
var b = new EmbedBuilder();
b.ThumbnailUrl = url;
});
}

/// <summary>
/// Tests the value of the <see cref="EmbedBuilder.Length"/> property when there are no fields set.
/// </summary>
[Fact]
public void Length_Empty()
{
var empty = new EmbedBuilder();
Assert.Equal(0, empty.Length);
}

/// <summary>
/// Tests the value of the <see cref="EmbedBuilder.Length"/> property when all fields are set.
/// </summary>
[Fact]
public void Length()
{
var e = new EmbedBuilder()
.WithAuthor(name, icon, url)
.WithColor(Color.Blue)
.WithDescription("This is the test description.")
.WithFooter("This is the footer", url)
.WithImageUrl(url)
.WithThumbnailUrl(url)
.WithTimestamp(DateTime.MinValue)
.WithTitle("This is the title")
.WithUrl(url)
.AddField("Field 1", "Inline", true)
.AddField("Field 2", "Not Inline", false);
Assert.Equal(100, e.Length);
}

/// <summary>
/// Tests the behavior of <see cref="EmbedBuilder.WithCurrentTimestamp"/>.
/// </summary>
[Fact]
public void WithCurrentTimestamp()
{
var e = new EmbedBuilder()
.WithCurrentTimestamp();
// ensure within a second of accuracy
Assert.Equal(DateTime.UtcNow, e.Timestamp.Value.UtcDateTime, TimeSpan.FromSeconds(1));
}

/// <summary>
/// Tests the behavior of <see cref="EmbedBuilder.WithColor(Color)"/>.
/// </summary>
[Fact]
public void WithColor()
{
// use WithColor
var e = new EmbedBuilder().WithColor(Color.Red);
Assert.Equal(Color.Red.RawValue, e.Color.Value.RawValue);
}

/// <summary>
/// Tests the behavior of <see cref="EmbedBuilder.WithFooter(Action{EmbedFooterBuilder})"/>
/// </summary>
[Fact]
public void WithFooter_ActionFooterBuilder()
{
var e = new EmbedBuilder()
.WithFooter(x =>
{
x.IconUrl = url;
x.Text = name;
});
Assert.Equal(url, e.Footer.IconUrl);
Assert.Equal(name, e.Footer.Text);
}

/// <summary>
/// Tests the behavior of <see cref="EmbedBuilder.WithFooter(EmbedFooterBuilder)"/>
/// </summary>
[Fact]
public void WithFooter_FooterBuilder()
{
var footer = new EmbedFooterBuilder()
{
IconUrl = url,
Text = name
};
var e = new EmbedBuilder()
.WithFooter(footer);
Assert.Equal(url, e.Footer.IconUrl);
Assert.Equal(name, e.Footer.Text);
// use the property
e = new EmbedBuilder();
e.Footer = footer;
Assert.Equal(url, e.Footer.IconUrl);
Assert.Equal(name, e.Footer.Text);
}

/// <summary>
/// Tests the behavior of <see cref="EmbedBuilder.WithFooter(string, string)"/>
/// </summary>
[Fact]
public void WithFooter_Strings()
{
var e = new EmbedBuilder()
.WithFooter(name, url);
Assert.Equal(url, e.Footer.IconUrl);
Assert.Equal(name, e.Footer.Text);
}

/// <summary>
/// Tests the behavior of <see cref="EmbedFooterBuilder"/>.
/// </summary>
[Fact]
public void EmbedFooterBuilder()
{
var footer = new EmbedFooterBuilder()
.WithIconUrl(url)
.WithText(name);
Assert.Equal(url, footer.IconUrl);
Assert.Equal(name, footer.Text);
}
/// <summary>
/// Tests that invalid URLs throw an <see cref="ArgumentException"/>.
/// </summary>
[Fact]
public void EmbedFooterBuilder_InvalidURL()
{
IEnumerable<string> InvalidUrls()
{
yield return "not a url";
}
foreach (var url in InvalidUrls())
{
Assert.Throws<ArgumentException>(() =>
{
new EmbedFooterBuilder().WithIconUrl(url);
});
}
}
/// <summary>
/// Tests that invalid text throws an <see cref="ArgumentException"/>.
/// </summary>
[Fact]
public void EmbedFooterBuilder_InvalidText()
{
Assert.Throws<ArgumentException>(() =>
{
new EmbedFooterBuilder().WithText(new string('a', 2049));
});
}
[Fact]
public void AddField_Strings()
{
var e = new EmbedBuilder()
.AddField("name", "value", true);
Assert.Equal("name", e.Fields[0].Name);
Assert.Equal("value", e.Fields[0].Value);
Assert.True(e.Fields[0].IsInline);
}
[Fact]
public void AddField_EmbedFieldBuilder()
{
var field = new EmbedFieldBuilder()
.WithIsInline(true)
.WithValue("value")
.WithName("name");
var e = new EmbedBuilder()
.AddField(field);
Assert.Equal("name", e.Fields[0].Name);
Assert.Equal("value", e.Fields[0].Value);
Assert.True(e.Fields[0].IsInline);
}
[Fact]
public void AddField_ActionEmbedFieldBuilder()
{
var e = new EmbedBuilder()
.AddField(x => x
.WithName("name")
.WithValue("value")
.WithIsInline(true));
Assert.Equal("name", e.Fields[0].Name);
Assert.Equal("value", e.Fields[0].Value);
Assert.True(e.Fields[0].IsInline);
}
[Fact]
public void AddField_TooManyFields()
{
var e = new EmbedBuilder();
for (var i = 0; i < 25; i++)
{
e = e.AddField("name", "value", false);
}
Assert.Throws<ArgumentException>(() =>
{
e = e.AddField("name", "value", false);
});
}
[Fact]
public void EmbedFieldBuilder()
{
var e = new EmbedFieldBuilder()
.WithIsInline(true)
.WithName("name")
.WithValue("value");
Assert.Equal("name", e.Name);
Assert.Equal("value", e.Value);
Assert.True(e.IsInline);
// use the properties
e = new EmbedFieldBuilder();
e.IsInline = true;
e.Name = "name";
e.Value = "value";
Assert.Equal("name", e.Name);
Assert.Equal("value", e.Value);
Assert.True(e.IsInline);
}
[Theory]
[InlineData("")]
[InlineData(" ")]
[InlineData(null)]
// 257 chars
[InlineData("jVyLChmA7aBZozXQuZ3VDEcwW6zOq0nteOVYBZi31ny73rpXfSSBXR4Jw6FiplDKQseKskwRMuBZkUewrewqAbkBZpslHirvC5nEzRySoDIdTRnkVvTXZUXg75l3bQCjuuHxDd6DfrY8ihd6yZX1Y0XFeg239YBcYV4TpL9uQ8H3HFYxrWhLlG2PRVjUmiglP5iXkawszNwMVm1SZ5LZT4jkMZHxFegVi7170d16iaPWOovu50aDDHy087XBtLKVa")]
// 257 chars of whitespace
[InlineData(" ")]
public void EmbedFieldBuilder_InvalidName(string name)
{
Assert.Throws<ArgumentException>(() => new EmbedFieldBuilder().WithName(name));
}
[Fact]
public void EmbedFieldBuilder_InvalidValue()
{
IEnumerable<string> GetInvalidValue()
{
yield return null;
yield return string.Empty;
yield return " ";
yield return new string('a', 1025);
};
foreach (var v in GetInvalidValue())
Assert.Throws<ArgumentException>(() => new EmbedFieldBuilder().WithValue(v));
}
}
}

test/Discord.Net.Tests/Tests.Emotes.cs → test/Discord.Net.Tests.Unit/EmoteTests.cs View File

@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Discord

+ 32
- 0
test/Discord.Net.Tests.Unit/FormatTests.cs View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Discord
{
public class FormatTests
{
[Theory]
[InlineData("@everyone", "@everyone")]
[InlineData(@"\", @"\\")]
[InlineData(@"*text*", @"\*text\*")]
[InlineData(@"~text~", @"\~text\~")]
[InlineData(@"`text`", @"\`text\`")]
[InlineData(@"_text_", @"\_text\_")]
public void Sanitize(string input, string expected)
{
Assert.Equal(expected, Format.Sanitize(input));
}
[Fact]
public void Code()
{
// no language
Assert.Equal("`test`", Format.Code("test"));
Assert.Equal("```\nanother\none\n```", Format.Code("another\none"));
// language specified
Assert.Equal("```cs\ntest\n```", Format.Code("test", "cs"));
Assert.Equal("```cs\nanother\none\n```", Format.Code("another\none", "cs"));
}
}
}

+ 164
- 0
test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs View File

@@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Discord
{
/// <summary>
/// Tests the behavior of the <see cref="Discord.GuildPermissions"/> type and related functions.
/// </summary>
public class GuildPermissionsTests
{
/// <summary>
/// Tests the default value of the <see cref="Discord.GuildPermissions"/> constructor.
/// </summary>
[Fact]
public void DefaultConstructor()
{
var p = new GuildPermissions();
Assert.Equal((ulong)0, p.RawValue);
Assert.Equal(GuildPermissions.None.RawValue, p.RawValue);
}

/// <summary>
/// Tests the behavior of the <see cref="Discord.GuildPermissions"/> raw value constructor.
/// </summary>
[Fact]
public void RawValueConstructor()
{
// returns all of the values that will be tested
// a Theory cannot be used here, because these values are not all constants
IEnumerable<ulong> GetTestValues()
{
yield return 0;
yield return GuildPermissions.None.RawValue;
yield return GuildPermissions.All.RawValue;
yield return GuildPermissions.Webhook.RawValue;
};

foreach (var rawValue in GetTestValues())
{
var p = new GuildPermissions(rawValue);
Assert.Equal(rawValue, p.RawValue);
}
}

/// <summary>
/// Tests the behavior of the <see cref="Discord.GuildPermissions"/> constructor for each
/// of it's flags.
/// </summary>
[Fact]
public void FlagsConstructor()
{
// util method for asserting that the constructor sets the given flag
void AssertFlag(Func<GuildPermissions> cstr, GuildPermission flag)
{
var p = cstr();
// ensure flag set to true
Assert.True(p.Has(flag));
// ensure only this flag is set
Assert.Equal((ulong)flag, p.RawValue);
}

AssertFlag(() => new GuildPermissions(createInstantInvite: true), GuildPermission.CreateInstantInvite);
AssertFlag(() => new GuildPermissions(kickMembers: true), GuildPermission.KickMembers);
AssertFlag(() => new GuildPermissions(banMembers: true), GuildPermission.BanMembers);
AssertFlag(() => new GuildPermissions(administrator: true), GuildPermission.Administrator);
AssertFlag(() => new GuildPermissions(manageChannels: true), GuildPermission.ManageChannels);
AssertFlag(() => new GuildPermissions(manageGuild: true), GuildPermission.ManageGuild);
AssertFlag(() => new GuildPermissions(addReactions: true), GuildPermission.AddReactions);
AssertFlag(() => new GuildPermissions(viewAuditLog: true), GuildPermission.ViewAuditLog);
AssertFlag(() => new GuildPermissions(viewChannel: true), GuildPermission.ViewChannel);
AssertFlag(() => new GuildPermissions(sendMessages: true), GuildPermission.SendMessages);
AssertFlag(() => new GuildPermissions(sendTTSMessages: true), GuildPermission.SendTTSMessages);
AssertFlag(() => new GuildPermissions(manageMessages: true), GuildPermission.ManageMessages);
AssertFlag(() => new GuildPermissions(embedLinks: true), GuildPermission.EmbedLinks);
AssertFlag(() => new GuildPermissions(attachFiles: true), GuildPermission.AttachFiles);
AssertFlag(() => new GuildPermissions(readMessageHistory: true), GuildPermission.ReadMessageHistory);
AssertFlag(() => new GuildPermissions(mentionEveryone: true), GuildPermission.MentionEveryone);
AssertFlag(() => new GuildPermissions(useExternalEmojis: true), GuildPermission.UseExternalEmojis);
AssertFlag(() => new GuildPermissions(connect: true), GuildPermission.Connect);
AssertFlag(() => new GuildPermissions(speak: true), GuildPermission.Speak);
AssertFlag(() => new GuildPermissions(muteMembers: true), GuildPermission.MuteMembers);
AssertFlag(() => new GuildPermissions(deafenMembers: true), GuildPermission.DeafenMembers);
AssertFlag(() => new GuildPermissions(moveMembers: true), GuildPermission.MoveMembers);
AssertFlag(() => new GuildPermissions(useVoiceActivation: true), GuildPermission.UseVAD);
AssertFlag(() => new GuildPermissions(prioritySpeaker: true), GuildPermission.PrioritySpeaker);
AssertFlag(() => new GuildPermissions(changeNickname: true), GuildPermission.ChangeNickname);
AssertFlag(() => new GuildPermissions(manageNicknames: true), GuildPermission.ManageNicknames);
AssertFlag(() => new GuildPermissions(manageRoles: true), GuildPermission.ManageRoles);
AssertFlag(() => new GuildPermissions(manageWebhooks: true), GuildPermission.ManageWebhooks);
AssertFlag(() => new GuildPermissions(manageEmojis: true), GuildPermission.ManageEmojis);
}

/// <summary>
/// Tests the behavior of <see cref="Discord.GuildPermissions.Modify(bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?, bool?)"/>
/// with each of the parameters.
/// </summary>
[Fact]
public void Modify()
{
// asserts that flag values can be checked
// and that flag values can be toggled on and off
// and that the behavior of ToList works as expected
void AssertUtil(GuildPermission permission,
Func<GuildPermissions, bool> has,
Func<GuildPermissions, bool, GuildPermissions> modify)
{
var perm = new GuildPermissions();
// ensure permission initially false
// use both the function and Has to ensure that the GetPermission
// function is working
Assert.False(has(perm));
Assert.False(perm.Has(permission));

// enable it, and ensure that it gets set
perm = modify(perm, true);
Assert.True(has(perm));
Assert.True(perm.Has(permission));

// check ToList behavior
var list = perm.ToList();
Assert.Contains(permission, list);
Assert.Single(list);

// set it false again
perm = modify(perm, false);
Assert.False(has(perm));
Assert.False(perm.Has(permission));

// ensure that no perms are set now
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);
}

AssertUtil(GuildPermission.CreateInstantInvite, x => x.CreateInstantInvite, (p, enable) => p.Modify(createInstantInvite: enable));
AssertUtil(GuildPermission.KickMembers, x => x.KickMembers, (p, enable) => p.Modify(kickMembers: enable));
AssertUtil(GuildPermission.BanMembers, x => x.BanMembers, (p, enable) => p.Modify(banMembers: enable));
AssertUtil(GuildPermission.Administrator, x => x.Administrator, (p, enable) => p.Modify(administrator: enable));
AssertUtil(GuildPermission.ManageChannels, x => x.ManageChannels, (p, enable) => p.Modify(manageChannels: enable));
AssertUtil(GuildPermission.ManageGuild, x => x.ManageGuild, (p, enable) => p.Modify(manageGuild: enable));
AssertUtil(GuildPermission.AddReactions, x => x.AddReactions, (p, enable) => p.Modify(addReactions: enable));
AssertUtil(GuildPermission.ViewAuditLog, x => x.ViewAuditLog, (p, enable) => p.Modify(viewAuditLog: enable));
AssertUtil(GuildPermission.ViewChannel, x => x.ViewChannel, (p, enable) => p.Modify(viewChannel: enable));
AssertUtil(GuildPermission.SendMessages, x => x.SendMessages, (p, enable) => p.Modify(sendMessages: enable));
AssertUtil(GuildPermission.SendTTSMessages, x => x.SendTTSMessages, (p, enable) => p.Modify(sendTTSMessages: enable));
AssertUtil(GuildPermission.ManageMessages, x => x.ManageMessages, (p, enable) => p.Modify(manageMessages: enable));
AssertUtil(GuildPermission.EmbedLinks, x => x.EmbedLinks, (p, enable) => p.Modify(embedLinks: enable));
AssertUtil(GuildPermission.AttachFiles, x => x.AttachFiles, (p, enable) => p.Modify(attachFiles: enable));
AssertUtil(GuildPermission.ReadMessageHistory, x => x.ReadMessageHistory, (p, enable) => p.Modify(readMessageHistory: enable));
AssertUtil(GuildPermission.MentionEveryone, x => x.MentionEveryone, (p, enable) => p.Modify(mentionEveryone: enable));
AssertUtil(GuildPermission.UseExternalEmojis, x => x.UseExternalEmojis, (p, enable) => p.Modify(useExternalEmojis: enable));
AssertUtil(GuildPermission.Connect, x => x.Connect, (p, enable) => p.Modify(connect: enable));
AssertUtil(GuildPermission.Speak, x => x.Speak, (p, enable) => p.Modify(speak: enable));
AssertUtil(GuildPermission.MuteMembers, x => x.MuteMembers, (p, enable) => p.Modify(muteMembers: enable));
AssertUtil(GuildPermission.MoveMembers, x => x.MoveMembers, (p, enable) => p.Modify(moveMembers: enable));
AssertUtil(GuildPermission.UseVAD, x => x.UseVAD, (p, enable) => p.Modify(useVoiceActivation: enable));
AssertUtil(GuildPermission.ChangeNickname, x => x.ChangeNickname, (p, enable) => p.Modify(changeNickname: enable));
AssertUtil(GuildPermission.ManageNicknames, x => x.ManageNicknames, (p, enable) => p.Modify(manageNicknames: enable));
AssertUtil(GuildPermission.ManageRoles, x => x.ManageRoles, (p, enable) => p.Modify(manageRoles: enable));
AssertUtil(GuildPermission.ManageWebhooks, x => x.ManageWebhooks, (p, enable) => p.Modify(manageWebhooks: enable));
AssertUtil(GuildPermission.ManageEmojis, x => x.ManageEmojis, (p, enable) => p.Modify(manageEmojis: enable));
}
}
}

+ 128
- 0
test/Discord.Net.Tests.Unit/MentionUtilsTests.cs View File

@@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Discord
{
/// <summary>
/// Tests the methods provided in <see cref="MentionUtils"/>.
/// </summary>
public class MentionUtilsTests
{
/// <summary>
/// Tests <see cref="MentionUtils.MentionUser(string, bool)"/>
/// </summary>
[Fact]
public void MentionUser()
{
Assert.Equal("<@!123>", MentionUtils.MentionUser(123u));
Assert.Equal("<@!123>", MentionUtils.MentionUser("123"));
Assert.Equal("<@!123>", MentionUtils.MentionUser("123", true));
Assert.Equal("<@123>", MentionUtils.MentionUser("123", false));
}
/// <summary>
/// Tests <see cref="MentionUtils.MentionChannel(string)"/>
/// </summary>
[Fact]
public void MentionChannel()
{
Assert.Equal("<#123>", MentionUtils.MentionChannel(123u));
Assert.Equal("<#123>", MentionUtils.MentionChannel("123"));
}
/// <summary>
/// Tests <see cref="MentionUtils.MentionRole(string)"/>
/// </summary>
[Fact]
public void MentionRole()
{
Assert.Equal("<@&123>", MentionUtils.MentionRole(123u));
Assert.Equal("<@&123>", MentionUtils.MentionRole("123"));
}
[Theory]
[InlineData("<@!123>", 123)]
[InlineData("<@123>", 123)]
public void ParseUser_Pass(string user, ulong id)
{
var parsed = MentionUtils.ParseUser(user);
Assert.Equal(id, parsed);

// also check tryparse
ulong result;
Assert.True(MentionUtils.TryParseUser(user, out result));
Assert.Equal(id, result);
}
[Theory]
[InlineData(" ")]
[InlineData("invalid")]
[InlineData("<12!3@>")]
[InlineData("<123>")]
public void ParseUser_Fail(string user)
{
Assert.Throws<ArgumentException>(() => MentionUtils.ParseUser(user));
Assert.False(MentionUtils.TryParseUser(user, out _));
}
[Fact]
public void ParseUser_Null()
{
Assert.Throws<NullReferenceException>(() => MentionUtils.ParseUser(null));
Assert.Throws<NullReferenceException>(() => MentionUtils.TryParseUser(null, out _));
}
[Theory]
[InlineData("<#123>", 123)]
public void ParseChannel_Pass(string channel, ulong id)
{
var parsed = MentionUtils.ParseChannel(channel);
Assert.Equal(id, parsed);

// also check tryparse
ulong result;
Assert.True(MentionUtils.TryParseChannel(channel, out result));
Assert.Equal(id, result);
}
[Theory]
[InlineData(" ")]
[InlineData("invalid")]
[InlineData("<12#3>")]
[InlineData("<123>")]
public void ParseChannel_Fail(string channel)
{
Assert.Throws<ArgumentException>(() => MentionUtils.ParseChannel(channel));
Assert.False(MentionUtils.TryParseChannel(channel, out _));
}
[Fact]
public void ParseChannel_Null()
{
Assert.Throws<NullReferenceException>(() => MentionUtils.ParseChannel(null));
Assert.Throws<NullReferenceException>(() => MentionUtils.TryParseChannel(null, out _));
}
[Theory]
[InlineData("<@&123>", 123)]
public void ParseRole_Pass(string role, ulong id)
{
var parsed = MentionUtils.ParseRole(role);
Assert.Equal(id, parsed);

// also check tryparse
ulong result;
Assert.True(MentionUtils.TryParseRole(role, out result));
Assert.Equal(id, result);
}
[Theory]
[InlineData(" ")]
[InlineData("invalid")]
[InlineData("<12@&3>")]
[InlineData("<123>")]
public void ParseRole_Fail(string role)
{
Assert.Throws<ArgumentException>(() => MentionUtils.ParseRole(role));
Assert.False(MentionUtils.TryParseRole(role, out _));
}
[Fact]
public void ParseRole_Null()
{
Assert.Throws<NullReferenceException>(() => MentionUtils.ParseRole(null));
Assert.Throws<NullReferenceException>(() => MentionUtils.TryParseRole(null, out _));
}
}
}

+ 84
- 0
test/Discord.Net.Tests.Unit/MockedEntities/MockedCategoryChannel.cs View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
internal sealed class MockedCategoryChannel : ICategoryChannel
{
public int Position => throw new NotImplementedException();

public IGuild Guild => throw new NotImplementedException();

public ulong GuildId => throw new NotImplementedException();

public IReadOnlyCollection<Overwrite> PermissionOverwrites => throw new NotImplementedException();

public string Name => throw new NotImplementedException();

public DateTimeOffset CreatedAt => throw new NotImplementedException();

public ulong Id => throw new NotImplementedException();

public Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public OverwritePermissions? GetPermissionOverwrite(IRole role)
{
throw new NotImplementedException();
}

public OverwritePermissions? GetPermissionOverwrite(IUser user)
{
throw new NotImplementedException();
}

public Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null)
{
throw new NotImplementedException();
}

Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
{
throw new NotImplementedException();
}

IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
{
throw new NotImplementedException();
}
}
}

+ 96
- 0
test/Discord.Net.Tests.Unit/MockedEntities/MockedDMChannel.cs View File

@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
internal sealed class MockedDMChannel : IDMChannel
{
public IUser Recipient => throw new NotImplementedException();

public IReadOnlyCollection<IUser> Recipients => throw new NotImplementedException();

public string Name => throw new NotImplementedException();

public DateTimeOffset CreatedAt => throw new NotImplementedException();

public ulong Id => throw new NotImplementedException();

public Task CloseAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IDisposable EnterTypingState(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IMessage> GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task TriggerTypingAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}
}
}

+ 105
- 0
test/Discord.Net.Tests.Unit/MockedEntities/MockedGroupChannel.cs View File

@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Discord.Audio;

namespace Discord
{
internal sealed class MockedGroupChannel : IGroupChannel
{
public IReadOnlyCollection<IUser> Recipients => throw new NotImplementedException();

public string Name => throw new NotImplementedException();

public DateTimeOffset CreatedAt => throw new NotImplementedException();

public ulong Id => throw new NotImplementedException();

public Task<IAudioClient> ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false)
{
throw new NotImplementedException();
}

public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DisconnectAsync()
{
throw new NotImplementedException();
}

public IDisposable EnterTypingState(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IMessage> GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task LeaveAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task TriggerTypingAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}
}
}

+ 29
- 0
test/Discord.Net.Tests.Unit/MockedEntities/MockedInvalidChannel.cs View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
/// <summary>
/// Represents a channel that is of an unrecognized type.
/// </summary>
internal sealed class MockedInvalidChannel : IChannel
{
public string Name => throw new NotImplementedException();

public DateTimeOffset CreatedAt => throw new NotImplementedException();

public ulong Id => throw new NotImplementedException();

public Task<IUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}
}
}

+ 205
- 0
test/Discord.Net.Tests.Unit/MockedEntities/MockedTextChannel.cs View File

@@ -0,0 +1,205 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
internal sealed class MockedTextChannel : ITextChannel
{
public bool IsNsfw => throw new NotImplementedException();

public string Topic => throw new NotImplementedException();

public int SlowModeInterval => throw new NotImplementedException();

public string Mention => throw new NotImplementedException();

public ulong? CategoryId => throw new NotImplementedException();

public int Position => throw new NotImplementedException();

public IGuild Guild => throw new NotImplementedException();

public ulong GuildId => throw new NotImplementedException();

public IReadOnlyCollection<Overwrite> PermissionOverwrites => throw new NotImplementedException();

public string Name => throw new NotImplementedException();

public DateTimeOffset CreatedAt => throw new NotImplementedException();

public ulong Id => throw new NotImplementedException();

public Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IWebhook> CreateWebhookAsync(string name, Stream avatar = null, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteMessagesAsync(IEnumerable<IMessage> messages, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteMessagesAsync(IEnumerable<ulong> messageIds, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IDisposable EnterTypingState(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<ICategoryChannel> GetCategoryAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IMessage> GetMessageAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = 100, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public OverwritePermissions? GetPermissionOverwrite(IRole role)
{
throw new NotImplementedException();
}

public OverwritePermissions? GetPermissionOverwrite(IUser user)
{
throw new NotImplementedException();
}

public Task<IReadOnlyCollection<IMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IWebhook> GetWebhookAsync(ulong id, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IReadOnlyCollection<IWebhook>> GetWebhooksAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false)
{
throw new NotImplementedException();
}

public Task<IUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task SyncPermissionsAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task TriggerTypingAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
{
throw new NotImplementedException();
}

IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
{
throw new NotImplementedException();
}
}
}

+ 126
- 0
test/Discord.Net.Tests.Unit/MockedEntities/MockedVoiceChannel.cs View File

@@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Discord.Audio;

namespace Discord
{
internal sealed class MockedVoiceChannel : IVoiceChannel
{
public int Bitrate => throw new NotImplementedException();

public int? UserLimit => throw new NotImplementedException();

public ulong? CategoryId => throw new NotImplementedException();

public int Position => throw new NotImplementedException();

public IGuild Guild => throw new NotImplementedException();

public ulong GuildId => throw new NotImplementedException();

public IReadOnlyCollection<Overwrite> PermissionOverwrites => throw new NotImplementedException();

public string Name => throw new NotImplementedException();

public DateTimeOffset CreatedAt => throw new NotImplementedException();

public ulong Id => throw new NotImplementedException();

public Task AddPermissionOverwriteAsync(IRole role, OverwritePermissions permissions, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task AddPermissionOverwriteAsync(IUser user, OverwritePermissions permissions, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IAudioClient> ConnectAsync(bool selfDeaf = false, bool selfMute = false, bool external = false)
{
throw new NotImplementedException();
}

public Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DeleteAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task DisconnectAsync()
{
throw new NotImplementedException();
}

public Task<ICategoryChannel> GetCategoryAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

public OverwritePermissions? GetPermissionOverwrite(IRole role)
{
throw new NotImplementedException();
}

public OverwritePermissions? GetPermissionOverwrite(IUser user)
{
throw new NotImplementedException();
}

public Task<IGuildUser> GetUserAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public IAsyncEnumerable<IReadOnlyCollection<IGuildUser>> GetUsersAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task ModifyAsync(Action<VoiceChannelProperties> func, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task ModifyAsync(Action<GuildChannelProperties> func, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task RemovePermissionOverwriteAsync(IRole role, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task RemovePermissionOverwriteAsync(IUser user, RequestOptions options = null)
{
throw new NotImplementedException();
}

public Task SyncPermissionsAsync(RequestOptions options = null)
{
throw new NotImplementedException();
}

Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
{
throw new NotImplementedException();
}

IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
{
throw new NotImplementedException();
}
}
}

+ 24
- 0
test/Discord.Net.Tests.Unit/SnowflakeUtilsTests.cs View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace Discord
{
public class SnowflakeUtilsTests
{
[Fact]
public void FromSnowflake()
{
// snowflake from a userid
var id = 163184946742034432u;
Assert.Equal(new DateTime(2016, 3, 26, 7, 18, 43), SnowflakeUtils.FromSnowflake(id).UtcDateTime, TimeSpan.FromSeconds(1));
}
[Fact]
public void ToSnowflake()
{
// most significant digits should match, but least significant digits cannot be determined from here
Assert.Equal(163184946184192000u, SnowflakeUtils.ToSnowflake(new DateTimeOffset(2016, 3, 26, 7, 18, 43, TimeSpan.Zero)));
}
}
}

test/Discord.Net.Tests/Tests.TokenUtils.cs → test/Discord.Net.Tests.Unit/TokenUtilsTests.cs View File

@@ -5,6 +5,9 @@ using Xunit;

namespace Discord
{
/// <summary>
/// Tests for the <see cref="Discord.TokenUtils"/> methods.
/// </summary>
public class TokenUtilsTests
{
/// <summary>
@@ -18,14 +21,14 @@ namespace Discord
[InlineData(" ")]
[InlineData(" ")]
[InlineData("\t")]
public void TestNullOrWhitespaceToken(string token)
public void NullOrWhitespaceToken(string token)
{
// an ArgumentNullException should be thrown, regardless of the TokenType
Assert.Throws<ArgumentNullException>(() => TokenUtils.ValidateToken(TokenType.Bearer, token));
Assert.Throws<ArgumentNullException>(() => TokenUtils.ValidateToken(TokenType.Bot, token));
Assert.Throws<ArgumentNullException>(() => TokenUtils.ValidateToken(TokenType.Webhook, token));
}
/// <summary>
/// Tests the behavior of <see cref="TokenUtils.ValidateToken(TokenType, string)"/>
/// to see that valid Webhook tokens do not throw Exceptions.
@@ -39,7 +42,7 @@ namespace Discord
[InlineData("6qrZcUqja7812RVdnEKjpzOL4CvHBFG")]
// client secret
[InlineData("937it3ow87i4ery69876wqire")]
public void TestWebhookTokenDoesNotThrowExceptions(string token)
public void WebhookTokenDoesNotThrowExceptions(string token)
{
TokenUtils.ValidateToken(TokenType.Webhook, token);
}
@@ -59,7 +62,7 @@ namespace Discord
[InlineData("6qrZcUqja7812RVdnEKjpzOL4CvHBFG")]
// client secret
[InlineData("937it3ow87i4ery69876wqire")]
public void TestBearerTokenDoesNotThrowExceptions(string token)
public void BearerTokenDoesNotThrowExceptions(string token)
{
TokenUtils.ValidateToken(TokenType.Bearer, token);
}
@@ -77,9 +80,7 @@ namespace Discord
// 59 char token
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWss")]
// simulated token with a very old user id
[InlineData("ODIzNjQ4MDEzNTAxMDcxMzY=.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKW")]
public void TestBotTokenDoesNotThrowExceptions(string token)
public void BotTokenDoesNotThrowExceptions(string token)
{
// This example token is pulled from the Discord Docs
// https://discordapp.com/developers/docs/reference#authentication-example-bot-token-authorization-header
@@ -112,7 +113,7 @@ namespace Discord
[InlineData("This is an invalid token, but it passes the check for string length.")]
// valid token, but passed in twice
[InlineData("MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWsMTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs")]
public void TestBotTokenInvalidThrowsArgumentException(string token)
public void BotTokenInvalidThrowsArgumentException(string token)
{
Assert.Throws<ArgumentException>(() => TokenUtils.ValidateToken(TokenType.Bot, token));
}
@@ -132,7 +133,7 @@ namespace Discord
[InlineData(-1)]
[InlineData(4)]
[InlineData(7)]
public void TestUnrecognizedTokenType(int type)
public void UnrecognizedTokenType(int type)
{
Assert.Throws<ArgumentException>(() =>
TokenUtils.ValidateToken((TokenType)type, "MTk4NjIyNDgzNDcxOTI1MjQ4.Cl2FMQ.ZnCjm1XVW7vRze4b7Cq4se7kKWs"));
@@ -154,7 +155,7 @@ namespace Discord
// should not throw an unexpected exception
[InlineData("", false)]
[InlineData(null, false)]
public void TestCheckBotTokenValidity(string token, bool expected)
public void CheckBotTokenValidity(string token, bool expected)
{
Assert.Equal(expected, TokenUtils.CheckBotTokenValidity(token));
}
@@ -163,16 +164,12 @@ namespace Discord
// cannot pass a ulong? as a param in InlineData, so have to have a separate param
// indicating if a value is null
[InlineData("NDI4NDc3OTQ0MDA5MTk1NTIw", false, 428477944009195520)]
// user id that has base 64 '=' padding
[InlineData("ODIzNjQ4MDEzNTAxMDcxMzY=", false, 82364801350107136)]
// user id that does not have '=' padding, and needs it
[InlineData("ODIzNjQ4MDEzNTAxMDcxMzY", false, 82364801350107136)]
// should return null w/o throwing other exceptions
[InlineData("", true, 0)]
[InlineData(" ", true, 0)]
[InlineData(null, true, 0)]
[InlineData("these chars aren't allowed @U#)*@#!)*", true, 0)]
public void TestDecodeBase64UserId(string encodedUserId, bool isNull, ulong expectedUserId)
public void DecodeBase64UserId(string encodedUserId, bool isNull, ulong expectedUserId)
{
var result = TokenUtils.DecodeBase64UserId(encodedUserId);
if (isNull)
@@ -180,37 +177,5 @@ namespace Discord
else
Assert.Equal(expectedUserId, result);
}

[Theory]
[InlineData("QQ", "QQ==")] // "A" encoded
[InlineData("QUE", "QUE=")] // "AA"
[InlineData("QUFB", "QUFB")] // "AAA"
[InlineData("QUFBQQ", "QUFBQQ==")] // "AAAA"
[InlineData("QUFBQUFB", "QUFBQUFB")] // "AAAAAA"
// strings that already contain padding will be returned, even if invalid
[InlineData("QUFBQQ==", "QUFBQQ==")]
[InlineData("QUFBQQ=", "QUFBQQ=")]
[InlineData("=", "=")]
public void TestPadBase64String(string input, string expected)
{
Assert.Equal(expected, TokenUtils.PadBase64String(input));
}

[Theory]
// no null, empty, or whitespace
[InlineData("", typeof(ArgumentNullException))]
[InlineData(" ", typeof(ArgumentNullException))]
[InlineData("\t", typeof(ArgumentNullException))]
[InlineData(null, typeof(ArgumentNullException))]
// cannot require 3 padding chars
[InlineData("A", typeof(FormatException))]
[InlineData("QUFBQ", typeof(FormatException))]
public void TestPadBase64StringException(string input, Type type)
{
Assert.Throws(type, () =>
{
TokenUtils.PadBase64String(input);
});
}
}
}

+ 142
- 0
test/Discord.Net.Tests.Unit/TypeReaderTests.cs View File

@@ -0,0 +1,142 @@
using Discord.Commands;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace Discord
{
public sealed class TypeReaderTests
{
[Fact]
public async Task TestNamedArgumentReader()
{
using (var commands = new CommandService())
{
var module = await commands.AddModuleAsync<TestModule>(null);

Assert.NotNull(module);
Assert.NotEmpty(module.Commands);

var cmd = module.Commands[0];
Assert.NotNull(cmd);
Assert.NotEmpty(cmd.Parameters);

var param = cmd.Parameters[0];
Assert.NotNull(param);
Assert.True(param.IsRemainder);

var result = await param.ParseAsync(null, "bar: hello foo: 42");
Assert.True(result.IsSuccess);

var m = result.BestMatch as ArgumentType;
Assert.NotNull(m);
Assert.Equal(expected: 42, actual: m.Foo);
Assert.Equal(expected: "hello", actual: m.Bar);
}
}

[Fact]
public async Task TestQuotedArgumentValue()
{
using (var commands = new CommandService())
{
var module = await commands.AddModuleAsync<TestModule>(null);

Assert.NotNull(module);
Assert.NotEmpty(module.Commands);

var cmd = module.Commands[0];
Assert.NotNull(cmd);
Assert.NotEmpty(cmd.Parameters);

var param = cmd.Parameters[0];
Assert.NotNull(param);
Assert.True(param.IsRemainder);

var result = await param.ParseAsync(null, "foo: 42 bar: 《hello》");
Assert.True(result.IsSuccess);

var m = result.BestMatch as ArgumentType;
Assert.NotNull(m);
Assert.Equal(expected: 42, actual: m.Foo);
Assert.Equal(expected: "hello", actual: m.Bar);
}
}

[Fact]
public async Task TestNonPatternInput()
{
using (var commands = new CommandService())
{
var module = await commands.AddModuleAsync<TestModule>(null);

Assert.NotNull(module);
Assert.NotEmpty(module.Commands);

var cmd = module.Commands[0];
Assert.NotNull(cmd);
Assert.NotEmpty(cmd.Parameters);

var param = cmd.Parameters[0];
Assert.NotNull(param);
Assert.True(param.IsRemainder);

var result = await param.ParseAsync(null, "foobar");
Assert.False(result.IsSuccess);
Assert.Equal(expected: CommandError.Exception, actual: result.Error);
}
}

[Fact]
public async Task TestMultiple()
{
using (var commands = new CommandService())
{
var module = await commands.AddModuleAsync<TestModule>(null);

Assert.NotNull(module);
Assert.NotEmpty(module.Commands);

var cmd = module.Commands[0];
Assert.NotNull(cmd);
Assert.NotEmpty(cmd.Parameters);

var param = cmd.Parameters[0];
Assert.NotNull(param);
Assert.True(param.IsRemainder);

var result = await param.ParseAsync(null, "manyints: \"1, 2, 3, 4, 5, 6, 7\"");
Assert.True(result.IsSuccess);

var m = result.BestMatch as ArgumentType;
Assert.NotNull(m);
Assert.Equal(expected: new int[] { 1, 2, 3, 4, 5, 6, 7 }, actual: m.ManyInts);
}
}
}

[NamedArgumentType]
public sealed class ArgumentType
{
public int Foo { get; set; }

[OverrideTypeReader(typeof(CustomTypeReader))]
public string Bar { get; set; }

public IEnumerable<int> ManyInts { get; set; }
}

public sealed class CustomTypeReader : TypeReader
{
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
=> Task.FromResult(TypeReaderResult.FromSuccess(input));
}

public sealed class TestModule : ModuleBase
{
[Command("test")]
public Task TestCommand(ArgumentType arg) => Task.Delay(0);
}
}

+ 0
- 35
test/Discord.Net.Tests/Discord.Net.Tests.csproj View File

@@ -1,35 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>Discord</RootNamespace>
<TargetFramework>netcoreapp2.1</TargetFramework>
<DebugType>portable</DebugType>
<NoWarn>IDISP001,IDISP002,IDISP004,IDISP005</NoWarn>
</PropertyGroup>
<ItemGroup>
<Content Include="xunit.runner.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Include="Tests.Permissions.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../../src/Discord.Net.Commands/Discord.Net.Commands.csproj" />
<ProjectReference Include="../../src/Discord.Net.Core/Discord.Net.Core.csproj" />
<ProjectReference Include="../../src/Discord.Net.Rest/Discord.Net.Rest.csproj" />
<ProjectReference Include="../../src/Discord.Net.Analyzers/Discord.Net.Analyzers.csproj" />
<ProjectReference Include="..\..\src\Discord.Net.Webhook\Discord.Net.Webhook.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Akavache" Version="6.0.31" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="xunit.runner.reporters" Version="2.4.1" />
</ItemGroup>
</Project>

+ 0
- 12
test/Discord.Net.Tests/Net/CacheInfo.cs View File

@@ -1,12 +0,0 @@
using Newtonsoft.Json;

namespace Discord.Net
{
internal class CacheInfo
{
[JsonProperty("guild_id")]
public ulong? GuildId { get; set; }
[JsonProperty("version")]
public uint Version { get; set; }
}
}

+ 0
- 123
test/Discord.Net.Tests/Net/CachedRestClient.cs View File

@@ -1,123 +0,0 @@
using Akavache;
using Akavache.Sqlite3;
using Discord.Net.Rest;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Threading;
using System.Threading.Tasks;
using Splat;

namespace Discord.Net
{
internal class CachedRestClient : IRestClient
{
private readonly Dictionary<string, string> _headers;
private IBlobCache _blobCache;
private string _baseUrl;
private CancellationTokenSource _cancelTokenSource;
private CancellationToken _cancelToken, _parentToken;
private bool _isDisposed;

public CacheInfo Info { get; private set; }

public CachedRestClient()
{
_headers = new Dictionary<string, string>();

_cancelTokenSource = new CancellationTokenSource();
_cancelToken = CancellationToken.None;
_parentToken = CancellationToken.None;

Locator.CurrentMutable.Register(() => Scheduler.Default, typeof(IScheduler), "Taskpool");
Locator.CurrentMutable.Register(() => new FilesystemProvider(), typeof(IFilesystemProvider), null);
Locator.CurrentMutable.Register(() => new HttpMixin(), typeof(IAkavacheHttpMixin), null);
//new Akavache.Sqlite3.Registrations().Register(Locator.CurrentMutable);
_blobCache = new SQLitePersistentBlobCache("cache.db");
}
private void Dispose(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
_blobCache.Dispose();
_cancelTokenSource?.Dispose();
}
_isDisposed = true;
}
}
public void Dispose()
{
Dispose(true);
}

public void SetUrl(string url)
{
_baseUrl = url;
}
public void SetHeader(string key, string value)
{
_headers[key] = value;
}
public void SetCancelToken(CancellationToken cancelToken)
{
_parentToken = cancelToken;
_cancelToken = CancellationTokenSource.CreateLinkedTokenSource(_parentToken, _cancelTokenSource.Token).Token;
}

public async Task<RestResponse> SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly, string reason = null)
{
if (method != "GET")
throw new InvalidOperationException("This RestClient only supports GET requests.");

string uri = Path.Combine(_baseUrl, endpoint);
var bytes = await _blobCache.DownloadUrl(uri, _headers);
return new RestResponse(HttpStatusCode.OK, _headers, new MemoryStream(bytes));
}
public Task<RestResponse> SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly, string reason = null)
{
throw new InvalidOperationException("This RestClient does not support payloads.");
}
public Task<RestResponse> SendAsync(string method, string endpoint, IReadOnlyDictionary<string, object> multipartParams, CancellationToken cancelToken, bool headerOnly, string reason = null)
{
throw new InvalidOperationException("This RestClient does not support multipart requests.");
}

public async Task ClearAsync()
{
await _blobCache.InvalidateAll();
}

public async Task LoadInfoAsync(ulong guildId)
{
if (Info != null)
return;

bool needsReset = false;
try
{
Info = await _blobCache.GetObject<CacheInfo>("info");
if (Info.GuildId != guildId)
needsReset = true;
}
catch (KeyNotFoundException)
{
needsReset = true;
}
if (needsReset)
{
Info = new CacheInfo() { GuildId = guildId, Version = 0 };
await SaveInfoAsync().ConfigureAwait(false);
}
}
public async Task SaveInfoAsync()
{
await ClearAsync().ConfigureAwait(false); //Version changed, invalidate cache
await _blobCache.InsertObject<CacheInfo>("info", Info);
}
}
}

+ 0
- 128
test/Discord.Net.Tests/Net/FilesystemProvider.cs View File

@@ -1,128 +0,0 @@
//From https://github.com/akavache/Akavache
//Copyright (c) 2012 GitHub
//TODO: Remove once netstandard support is added

using Akavache;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reactive;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Reflection;

namespace Discord
{
public class FilesystemProvider : IFilesystemProvider
{
public IObservable<Stream> OpenFileForReadAsync(string path, IScheduler scheduler)
{
return SafeOpenFileAsync(path, FileMode.Open, FileAccess.Read, FileShare.Read, scheduler);
}

public IObservable<Stream> OpenFileForWriteAsync(string path, IScheduler scheduler)
{
return SafeOpenFileAsync(path, FileMode.Create, FileAccess.Write, FileShare.None, scheduler);
}

public IObservable<Unit> CreateRecursive(string path)
{
CreateRecursive(new DirectoryInfo(path));
return Observable.Return(Unit.Default);
}

public IObservable<Unit> Delete(string path)
{
return Observable.Start(() => File.Delete(path), Scheduler.Default);
}
public string GetDefaultRoamingCacheDirectory()
{
throw new NotSupportedException();
}

public string GetDefaultSecretCacheDirectory()
{
throw new NotSupportedException();
}

public string GetDefaultLocalMachineCacheDirectory()
{
throw new NotSupportedException();
}

protected static string GetAssemblyDirectoryName()
{
var assemblyDirectoryName = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
Debug.Assert(assemblyDirectoryName != null, "The directory name of the assembly location is null");
return assemblyDirectoryName;
}

private static IObservable<Stream> SafeOpenFileAsync(string path, FileMode mode, FileAccess access, FileShare share, IScheduler scheduler = null)
{
scheduler = scheduler ?? Scheduler.Default;
var ret = new AsyncSubject<Stream>();

Observable.Start(() =>
{
try
{
var createModes = new[]
{
FileMode.Create,
FileMode.CreateNew,
FileMode.OpenOrCreate,
};


// NB: We do this (even though it's incorrect!) because
// throwing lots of 1st chance exceptions makes debugging
// obnoxious, as well as a bug in VS where it detects
// exceptions caught by Observable.Start as Unhandled.
if (!createModes.Contains(mode) && !File.Exists(path))
{
ret.OnError(new FileNotFoundException());
return;
}

Observable.Start(() => new FileStream(path, mode, access, share, 4096, false), scheduler).Cast<Stream>().Subscribe(ret);
}
catch (Exception ex)
{
ret.OnError(ex);
}
}, scheduler);

return ret;
}
private static void CreateRecursive(DirectoryInfo info)
{
SplitFullPath(info).Aggregate((parent, dir) =>
{
var path = Path.Combine(parent, dir);
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
return path;
});
}

private static IEnumerable<string> SplitFullPath(DirectoryInfo info)
{
var root = Path.GetPathRoot(info.FullName);
var components = new List<string>();
for (var path = info.FullName; path != root && path != null; path = Path.GetDirectoryName(path))
{
var filename = Path.GetFileName(path);
if (String.IsNullOrEmpty(filename))
continue;
components.Add(filename);
}
components.Add(root);
components.Reverse();
return components;
}
}
}

+ 0
- 144
test/Discord.Net.Tests/Net/HttpMixin.cs View File

@@ -1,144 +0,0 @@
//From https://github.com/akavache/Akavache
//Copyright (c) 2012 GitHub
//TODO: Remove once netstandard support is added

#pragma warning disable CS0618

using Akavache;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Reactive;
using System.Reactive.Threading.Tasks;

namespace Discord.Net
{
public class HttpMixin : IAkavacheHttpMixin
{
/// <summary>
/// Download data from an HTTP URL and insert the result into the
/// cache. If the data is already in the cache, this returns
/// a cached value. The URL itself is used as the key.
/// </summary>
/// <param name="url">The URL to download.</param>
/// <param name="headers">An optional Dictionary containing the HTTP
/// request headers.</param>
/// <param name="fetchAlways">Force a web request to always be issued, skipping the cache.</param>
/// <param name="absoluteExpiration">An optional expiration date.</param>
/// <returns>The data downloaded from the URL.</returns>
public IObservable<byte[]> DownloadUrl(IBlobCache This, string url, IDictionary<string, string> headers = null, bool fetchAlways = false, DateTimeOffset? absoluteExpiration = null)
{
return This.DownloadUrl(url, url, headers, fetchAlways, absoluteExpiration);
}

/// <summary>
/// Download data from an HTTP URL and insert the result into the
/// cache. If the data is already in the cache, this returns
/// a cached value. An explicit key is provided rather than the URL itself.
/// </summary>
/// <param name="key">The key to store with.</param>
/// <param name="url">The URL to download.</param>
/// <param name="headers">An optional Dictionary containing the HTTP
/// request headers.</param>
/// <param name="fetchAlways">Force a web request to always be issued, skipping the cache.</param>
/// <param name="absoluteExpiration">An optional expiration date.</param>
/// <returns>The data downloaded from the URL.</returns>
public IObservable<byte[]> DownloadUrl(IBlobCache This, string key, string url, IDictionary<string, string> headers = null, bool fetchAlways = false, DateTimeOffset? absoluteExpiration = null)
{
var doFetch = MakeWebRequest(new Uri(url), headers).SelectMany(x => ProcessWebResponse(x, url, absoluteExpiration));
var fetchAndCache = doFetch.SelectMany(x => This.Insert(key, x, absoluteExpiration).Select(_ => x));

var ret = default(IObservable<byte[]>);
if (!fetchAlways)
{
ret = This.Get(key).Catch(fetchAndCache);
}
else
{
ret = fetchAndCache;
}

var conn = ret.PublishLast();
conn.Connect();
return conn;
}

IObservable<byte[]> ProcessWebResponse(WebResponse wr, string url, DateTimeOffset? absoluteExpiration)
{
var hwr = (HttpWebResponse)wr;
Debug.Assert(hwr != null, "The Web Response is somehow null but shouldn't be.");
if ((int)hwr.StatusCode >= 400)
{
return Observable.Throw<byte[]>(new WebException(hwr.StatusDescription));
}

var ms = new MemoryStream();
using (var responseStream = hwr.GetResponseStream())
{
Debug.Assert(responseStream != null, "The response stream is somehow null");
responseStream.CopyTo(ms);
}

var ret = ms.ToArray();
return Observable.Return(ret);
}

static IObservable<WebResponse> MakeWebRequest(
Uri uri,
IDictionary<string, string> headers = null,
string content = null,
int retries = 3,
TimeSpan? timeout = null)
{
IObservable<WebResponse> request;

request = Observable.Defer(() =>
{
var hwr = CreateWebRequest(uri, headers);

if (content == null)
return Observable.FromAsyncPattern<WebResponse>(hwr.BeginGetResponse, hwr.EndGetResponse)();

var buf = Encoding.UTF8.GetBytes(content);

// NB: You'd think that BeginGetResponse would never block,
// seeing as how it's asynchronous. You'd be wrong :-/
var ret = new AsyncSubject<WebResponse>();
Observable.Start(() =>
{
Observable.FromAsyncPattern<Stream>(hwr.BeginGetRequestStream, hwr.EndGetRequestStream)()
.SelectMany(x => WriteAsyncRx(x, buf, 0, buf.Length))
.SelectMany(_ => Observable.FromAsyncPattern<WebResponse>(hwr.BeginGetResponse, hwr.EndGetResponse)())
.Multicast(ret).Connect();
}, BlobCache.TaskpoolScheduler);

return ret;
});

return request.Timeout(timeout ?? TimeSpan.FromSeconds(15), BlobCache.TaskpoolScheduler).Retry(retries);
}

private static WebRequest CreateWebRequest(Uri uri, IDictionary<string, string> headers)
{
var hwr = WebRequest.Create(uri);
if (headers != null)
{
foreach (var x in headers)
{
hwr.Headers[x.Key] = x.Value;
}
}
return hwr;
}

private static IObservable<Unit> WriteAsyncRx(Stream stream, byte[] data, int start, int length)
{
return stream.WriteAsync(data, start, length).ToObservable();
}
}
}

+ 0
- 33
test/Discord.Net.Tests/TestConfig.cs View File

@@ -1,33 +0,0 @@
using Newtonsoft.Json;
using System.IO;
using System;

namespace Discord
{
internal class TestConfig
{
[JsonProperty("token")]
public string Token { get; private set; }
[JsonProperty("guild_id")]
public ulong GuildId { get; private set; }
public static TestConfig LoadFile(string path)
{
if (File.Exists(path))
{
using (var stream = new FileStream(path, FileMode.Open))
using (var reader = new StreamReader(stream))
using (var jsonReader = new JsonTextReader(reader))
return new JsonSerializer().Deserialize<TestConfig>(jsonReader);
}
else
{
return new TestConfig()
{
Token = Environment.GetEnvironmentVariable("DNET_TEST_TOKEN"),
GuildId = ulong.Parse(Environment.GetEnvironmentVariable("DNET_TEST_GUILDID"))
};
}
}
}
}

+ 0
- 177
test/Discord.Net.Tests/Tests.ChannelPermissions.cs View File

@@ -1,177 +0,0 @@
using System;
using System.Threading.Tasks;
using Xunit;

namespace Discord
{
public class ChannelPermissionsTests
{
// seems like all these tests are broken
/*[Fact]
public Task TestChannelPermission()
{
var perm = new ChannelPermissions();

// check initial values
Assert.Equal((ulong)0, perm.RawValue);
Assert.Equal(ChannelPermissions.None.RawValue, perm.RawValue);

// permissions list empty by default
Assert.Empty(perm.ToList());

// test modify with no parameters
var copy = perm.Modify();
Assert.Equal((ulong)0, copy.RawValue);

// test modify with no parameters after using all
copy = ChannelPermissions.Text;
var modified = copy.Modify(); // no params should not change the result
Assert.Equal(ChannelPermissions.Text.RawValue, modified.RawValue);

copy = ChannelPermissions.Voice;
modified = copy.Modify(); // no params should not change the result
Assert.Equal(ChannelPermissions.Voice.RawValue, modified.RawValue);

copy = ChannelPermissions.Group;
modified = copy.Modify(); // no params should not change the result
Assert.Equal(ChannelPermissions.Group.RawValue, modified.RawValue);

copy = ChannelPermissions.DM;
modified = copy.Modify(); // no params should not change the result
Assert.Equal(ChannelPermissions.DM.RawValue, modified.RawValue);

copy = new ChannelPermissions(useExternalEmojis: true);
modified = copy.Modify();
Assert.Equal(copy.RawValue, modified.RawValue);

// test the values that are returned by ChannelPermission.All
Assert.Equal((ulong)0, ChannelPermissions.None.RawValue);

// for text channels
ulong textChannel = (ulong)( ChannelPermission.CreateInstantInvite
| ChannelPermission.ManageChannels
| ChannelPermission.AddReactions
| ChannelPermission.ViewChannel
| ChannelPermission.SendMessages
| ChannelPermission.SendTTSMessages
| ChannelPermission.ManageMessages
| ChannelPermission.EmbedLinks
| ChannelPermission.AttachFiles
| ChannelPermission.ReadMessageHistory
| ChannelPermission.MentionEveryone
| ChannelPermission.UseExternalEmojis
| ChannelPermission.ManageRoles
| ChannelPermission.ManageWebhooks);

Assert.Equal(textChannel, ChannelPermissions.Text.RawValue);

// voice channels
ulong voiceChannel = (ulong)(
ChannelPermission.CreateInstantInvite
| ChannelPermission.ManageChannels
| ChannelPermission.ViewChannel
| ChannelPermission.Connect
| ChannelPermission.Speak
| ChannelPermission.MuteMembers
| ChannelPermission.DeafenMembers
| ChannelPermission.MoveMembers
| ChannelPermission.UseVAD
| ChannelPermission.ManageRoles
| ChannelPermission.PrioritySpeaker);

Assert.Equal(voiceChannel, ChannelPermissions.Voice.RawValue);

// DM Channels
ulong dmChannel = (ulong)(
ChannelPermission.ViewChannel
| ChannelPermission.SendMessages
| ChannelPermission.EmbedLinks
| ChannelPermission.AttachFiles
| ChannelPermission.ReadMessageHistory
| ChannelPermission.UseExternalEmojis
| ChannelPermission.Connect
| ChannelPermission.Speak
| ChannelPermission.UseVAD
);
//Assert.Equal(dmChannel, ChannelPermissions.DM.RawValue);
// TODO: this test is failing and that's a bad thing

// group channel
ulong groupChannel = (ulong)(
ChannelPermission.SendMessages
| ChannelPermission.EmbedLinks
| ChannelPermission.AttachFiles
| ChannelPermission.SendTTSMessages
| ChannelPermission.Connect
| ChannelPermission.Speak
| ChannelPermission.UseVAD
);
// TODO: this test is also broken
//Assert.Equal(groupChannel, ChannelPermissions.Group.RawValue);
return Task.CompletedTask;
}*/
[Fact]
public Task TestChannelPermissionModify()
{
// test that channel permissions could be modified correctly
var perm = new ChannelPermissions();

void Check(ChannelPermission permission,
Func<ChannelPermissions, bool> has,
Func<ChannelPermissions, bool, ChannelPermissions> modify)
{
// ensure permission initially false
// use both the function and Has to ensure that the GetPermission
// function is working
Assert.False(has(perm));
Assert.False(perm.Has(permission));

// enable it, and ensure that it gets set
perm = modify(perm, true);
Assert.True(has(perm));
Assert.True(perm.Has(permission));

// set it false again
perm = modify(perm, false);
Assert.False(has(perm));
Assert.False(perm.Has(permission));

// ensure that no perms are set now
Assert.Equal(ChannelPermissions.None.RawValue, perm.RawValue);
}

Check(ChannelPermission.CreateInstantInvite, x => x.CreateInstantInvite, (p, enable) => p.Modify(createInstantInvite: enable));
Check(ChannelPermission.ManageChannels, x => x.ManageChannel, (p, enable) => p.Modify(manageChannel: enable));
Check(ChannelPermission.AddReactions, x => x.AddReactions, (p, enable) => p.Modify(addReactions: enable));
Check(ChannelPermission.ViewChannel, x => x.ViewChannel, (p, enable) => p.Modify(viewChannel: enable));
Check(ChannelPermission.SendMessages, x => x.SendMessages, (p, enable) => p.Modify(sendMessages: enable));
Check(ChannelPermission.SendTTSMessages, x => x.SendTTSMessages, (p, enable) => p.Modify(sendTTSMessages: enable));
Check(ChannelPermission.ManageMessages, x => x.ManageMessages, (p, enable) => p.Modify(manageMessages: enable));
Check(ChannelPermission.EmbedLinks, x => x.EmbedLinks, (p, enable) => p.Modify(embedLinks: enable));
Check(ChannelPermission.AttachFiles, x => x.AttachFiles, (p, enable) => p.Modify(attachFiles: enable));
Check(ChannelPermission.ReadMessageHistory, x => x.ReadMessageHistory, (p, enable) => p.Modify(readMessageHistory: enable));
Check(ChannelPermission.MentionEveryone, x => x.MentionEveryone, (p, enable) => p.Modify(mentionEveryone: enable));
Check(ChannelPermission.UseExternalEmojis, x => x.UseExternalEmojis, (p, enable) => p.Modify(useExternalEmojis: enable));
Check(ChannelPermission.Connect, x => x.Connect, (p, enable) => p.Modify(connect: enable));
Check(ChannelPermission.Speak, x => x.Speak, (p, enable) => p.Modify(speak: enable));
Check(ChannelPermission.MuteMembers, x => x.MuteMembers, (p, enable) => p.Modify(muteMembers: enable));
Check(ChannelPermission.DeafenMembers, x => x.DeafenMembers, (p, enable) => p.Modify(deafenMembers: enable));
Check(ChannelPermission.MoveMembers, x => x.MoveMembers, (p, enable) => p.Modify(moveMembers: enable));
Check(ChannelPermission.UseVAD, x => x.UseVAD, (p, enable) => p.Modify(useVoiceActivation: enable));
Check(ChannelPermission.ManageRoles, x => x.ManageRoles, (p, enable) => p.Modify(manageRoles: enable));
Check(ChannelPermission.ManageWebhooks, x => x.ManageWebhooks, (p, enable) => p.Modify(manageWebhooks: enable));
Check(ChannelPermission.PrioritySpeaker, x => x.PrioritySpeaker, (p, enable) => p.Modify(prioritySpeaker: enable));

return Task.CompletedTask;
}

[Fact]
public Task TestChannelTypeResolution()
{
ITextChannel someChannel = null;
// null channels will throw exception
Assert.Throws<ArgumentException>(() => ChannelPermissions.All(someChannel));
return Task.CompletedTask;
}
}
}

+ 0
- 218
test/Discord.Net.Tests/Tests.Channels.cs View File

@@ -1,218 +0,0 @@
using Discord.Rest;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
#if IXTEST
namespace Discord
{
public partial class Tests
{
internal static async Task Migration_CreateTextChannels(DiscordRestClient client, RestGuild guild)
{
var text1 = await guild.GetDefaultChannelAsync();
var text2 = await guild.CreateTextChannelAsync("text2");
var text3 = await guild.CreateTextChannelAsync("text3");
var text4 = await guild.CreateTextChannelAsync("text4");
var text5 = await guild.CreateTextChannelAsync("text5");

// create a channel category
var cat1 = await guild.CreateCategoryChannelAsync("cat1");

if (text1 == null)
{
// the guild did not have a default channel, so make a new one
text1 = await guild.CreateTextChannelAsync("default");
}

//Modify #general
await text1.ModifyAsync(x =>
{
x.Name = "text1";
x.Position = 1;
x.Topic = "Topic1";
x.CategoryId = cat1.Id;
});

await text2.ModifyAsync(x =>
{
x.Position = 2;
x.CategoryId = cat1.Id;
});
await text3.ModifyAsync(x =>
{
x.Topic = "Topic2";
});
await text4.ModifyAsync(x =>
{
x.Position = 3;
x.Topic = "Topic2";
});
await text5.ModifyAsync(x =>
{
});

CheckTextChannels(guild, text1, text2, text3, text4, text5);
}
[Fact]
public async Task TestTextChannels()
{
CheckTextChannels(_guild, (await _guild.GetTextChannelsAsync()).ToArray());
}
private static void CheckTextChannels(RestGuild guild, params RestTextChannel[] textChannels)
{
Assert.Equal(5, textChannels.Length);
Assert.All(textChannels, x =>
{
Assert.NotNull(x);
Assert.NotEqual(0UL, x.Id);
Assert.True(x.Position >= 0);
});

var text1 = textChannels.FirstOrDefault(x => x.Name == "text1");
var text2 = textChannels.FirstOrDefault(x => x.Name == "text2");
var text3 = textChannels.FirstOrDefault(x => x.Name == "text3");
var text4 = textChannels.FirstOrDefault(x => x.Name == "text4");
var text5 = textChannels.FirstOrDefault(x => x.Name == "text5");

Assert.NotNull(text1);
//Assert.True(text1.Id == guild.DefaultChannelId);
Assert.Equal(1, text1.Position);
Assert.Equal("Topic1", text1.Topic);

Assert.NotNull(text2);
Assert.Equal(2, text2.Position);
Assert.Null(text2.Topic);

Assert.NotNull(text3);
Assert.Equal("Topic2", text3.Topic);

Assert.NotNull(text4);
Assert.Equal(3, text4.Position);
Assert.Equal("Topic2", text4.Topic);

Assert.NotNull(text5);
Assert.Null(text5.Topic);
}

internal static async Task Migration_CreateVoiceChannels(DiscordRestClient client, RestGuild guild)
{
var voice1 = await guild.CreateVoiceChannelAsync("voice1");
var voice2 = await guild.CreateVoiceChannelAsync("voice2");
var voice3 = await guild.CreateVoiceChannelAsync("voice3");

var cat2 = await guild.CreateCategoryChannelAsync("cat2");

await voice1.ModifyAsync(x =>
{
x.Bitrate = 96000;
x.Position = 1;
x.CategoryId = cat2.Id;
});
await voice2.ModifyAsync(x =>
{
x.UserLimit = null;
});
await voice3.ModifyAsync(x =>
{
x.Bitrate = 8000;
x.Position = 1;
x.UserLimit = 16;
x.CategoryId = cat2.Id;
});

CheckVoiceChannels(voice1, voice2, voice3);
}
[Fact]
public async Task TestVoiceChannels()
{
CheckVoiceChannels((await _guild.GetVoiceChannelsAsync()).ToArray());
}
private static void CheckVoiceChannels(params RestVoiceChannel[] voiceChannels)
{
Assert.Equal(3, voiceChannels.Length);
Assert.All(voiceChannels, x =>
{
Assert.NotNull(x);
Assert.NotEqual(0UL, x.Id);
Assert.NotEqual(0, x.UserLimit);
Assert.True(x.Bitrate > 0);
Assert.True(x.Position >= 0);
});

var voice1 = voiceChannels.FirstOrDefault(x => x.Name == "voice1");
var voice2 = voiceChannels.FirstOrDefault(x => x.Name == "voice2");
var voice3 = voiceChannels.FirstOrDefault(x => x.Name == "voice3");

Assert.NotNull(voice1);
Assert.Equal(96000, voice1.Bitrate);
Assert.Equal(1, voice1.Position);

Assert.NotNull(voice2);
Assert.Null(voice2.UserLimit);

Assert.NotNull(voice3);
Assert.Equal(8000, voice3.Bitrate);
Assert.Equal(1, voice3.Position);
Assert.Equal(16, voice3.UserLimit);
}

[Fact]
public async Task TestChannelCategories()
{
// (await _guild.GetVoiceChannelsAsync()).ToArray()
var channels = await _guild.GetCategoryChannelsAsync();

await CheckChannelCategories(channels.ToArray(), (await _guild.GetChannelsAsync()).ToArray());
}

private async Task CheckChannelCategories(RestCategoryChannel[] categories, RestGuildChannel[] allChannels)
{
// 2 categories
Assert.Equal(2, categories.Length);

var cat1 = categories.FirstOrDefault(x => x.Name == "cat1");
var cat2 = categories.FirstOrDefault(x => x.Name == "cat2");

Assert.NotNull(cat1);
Assert.NotNull(cat2);

// get text1, text2, ensure they have category id == cat1
var text1 = allChannels.FirstOrDefault(x => x.Name == "text1") as RestTextChannel;
var text2 = allChannels.FirstOrDefault(x => x.Name == "text2") as RestTextChannel;

Assert.NotNull(text1);
Assert.NotNull(text2);

// check that CategoryID and .GetCategoryAsync work correctly
// for both of the text channels
Assert.Equal(text1.CategoryId, cat1.Id);
var text1Cat = await text1.GetCategoryAsync();
Assert.Equal(text1Cat.Id, cat1.Id);
Assert.Equal(text1Cat.Name, cat1.Name);

Assert.Equal(text2.CategoryId, cat1.Id);
var text2Cat = await text2.GetCategoryAsync();
Assert.Equal(text2Cat.Id, cat1.Id);
Assert.Equal(text2Cat.Name, cat1.Name);

// do the same for the voice channels
var voice1 = allChannels.FirstOrDefault(x => x.Name == "voice1") as RestVoiceChannel;
var voice3 = allChannels.FirstOrDefault(x => x.Name == "voice3") as RestVoiceChannel;

Assert.NotNull(voice1);
Assert.NotNull(voice3);

Assert.Equal(voice1.CategoryId, cat2.Id);
var voice1Cat = await voice1.GetCategoryAsync();
Assert.Equal(voice1Cat.Id, cat2.Id);
Assert.Equal(voice1Cat.Name, cat2.Name);

Assert.Equal(voice3.CategoryId, cat2.Id);
var voice3Cat = await voice3.GetCategoryAsync();
Assert.Equal(voice3Cat.Id, cat2.Id);
Assert.Equal(voice3Cat.Name, cat2.Name);

}
}
}
#endif

+ 0
- 342
test/Discord.Net.Tests/Tests.Guilds.cs View File

@@ -1,342 +0,0 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
#if IXTEST
namespace Discord
{
public partial class Tests
{
/// <summary>
/// Tests the behavior of modifying the ExplicitContentFilter property of a Guild.
/// </summary>
[Fact]
public async Task TestExplicitContentFilter()
{
foreach (var level in Enum.GetValues(typeof(ExplicitContentFilterLevel)))
{
await _guild.ModifyAsync(x => x.ExplicitContentFilter = (ExplicitContentFilterLevel)level);
await _guild.UpdateAsync();
Assert.Equal(level, _guild.ExplicitContentFilter);
}
}

/// <summary>
/// Tests the behavior of the GuildPermissions class.
/// </summary>
[Fact]
public Task TestGuildPermission()
{
// Test Guild Permission Constructors
var perm = new GuildPermissions();

// the default raw value is 0
Assert.Equal((ulong)0, perm.RawValue);
// also check that it is the same as none
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// permissions list is empty by default
Assert.Empty(perm.ToList());
Assert.NotNull(perm.ToList());

// Test modify with no parameters
var copy = perm.Modify();
// ensure that the raw values match
Assert.Equal((ulong)0, copy.RawValue);

// test modify with no parameters
copy = GuildPermissions.None.Modify();
Assert.Equal(GuildPermissions.None.RawValue, copy.RawValue);

// test modify with no parameters on all permissions
copy = GuildPermissions.All.Modify();
Assert.Equal(GuildPermissions.All.RawValue, copy.RawValue);

// test modify with no parameters on webhook permissions
copy = GuildPermissions.Webhook.Modify();
Assert.Equal(GuildPermissions.Webhook.RawValue, copy.RawValue);

// Get all distinct values (ReadMessages = ViewChannel)
var enumValues = (Enum.GetValues(typeof(GuildPermission)) as GuildPermission[])
.Distinct()
.ToArray();
// test GuildPermissions.All
ulong sumOfAllGuildPermissions = 0;
foreach(var v in enumValues)
{
sumOfAllGuildPermissions |= (ulong)v;
}

// assert that the raw values match
Assert.Equal(sumOfAllGuildPermissions, GuildPermissions.All.RawValue);
Assert.Equal((ulong)0, GuildPermissions.None.RawValue);

// assert that GuildPermissions.All contains the same number of permissions as the
// GuildPermissions enum
Assert.Equal(enumValues.Length, GuildPermissions.All.ToList().Count);

// assert that webhook has the same raw value
ulong webHookPermissions = (ulong)(
GuildPermission.SendMessages | GuildPermission.SendTTSMessages | GuildPermission.EmbedLinks |
GuildPermission.AttachFiles);
Assert.Equal(webHookPermissions, GuildPermissions.Webhook.RawValue);

return Task.CompletedTask;
}

[Fact]
public Task TestGuildPermissionModify()
{
var perm = new GuildPermissions();

// tests each of the parameters of Modify one by one

// test modify with each of the parameters
// test initially false state
Assert.False(perm.CreateInstantInvite);

// ensure that when we modify it the parameter works
perm = perm.Modify(createInstantInvite: true);
Assert.True(perm.CreateInstantInvite);
Assert.Equal((ulong)GuildPermission.CreateInstantInvite, perm.RawValue);

// set it false again, then move on to the next permission
perm = perm.Modify(createInstantInvite: false);
Assert.False(perm.CreateInstantInvite);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(kickMembers: true);
Assert.True(perm.KickMembers);
Assert.Equal((ulong)GuildPermission.KickMembers, perm.RawValue);

perm = perm.Modify(kickMembers: false);
Assert.False(perm.KickMembers);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(banMembers: true);
Assert.True(perm.BanMembers);
Assert.Equal((ulong)GuildPermission.BanMembers, perm.RawValue);

perm = perm.Modify(banMembers: false);
Assert.False(perm.BanMembers);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(administrator: true);
Assert.True(perm.Administrator);
Assert.Equal((ulong)GuildPermission.Administrator, perm.RawValue);

perm = perm.Modify(administrator: false);
Assert.False(perm.Administrator);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(manageChannels: true);
Assert.True(perm.ManageChannels);
Assert.Equal((ulong)GuildPermission.ManageChannels, perm.RawValue);

perm = perm.Modify(manageChannels: false);
Assert.False(perm.ManageChannels);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(manageGuild: true);
Assert.True(perm.ManageGuild);
Assert.Equal((ulong)GuildPermission.ManageGuild, perm.RawValue);

perm = perm.Modify(manageGuild: false);
Assert.False(perm.ManageGuild);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);


// individual permission test
perm = perm.Modify(addReactions: true);
Assert.True(perm.AddReactions);
Assert.Equal((ulong)GuildPermission.AddReactions, perm.RawValue);

perm = perm.Modify(addReactions: false);
Assert.False(perm.AddReactions);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);


// individual permission test
perm = perm.Modify(viewAuditLog: true);
Assert.True(perm.ViewAuditLog);
Assert.Equal((ulong)GuildPermission.ViewAuditLog, perm.RawValue);

perm = perm.Modify(viewAuditLog: false);
Assert.False(perm.ViewAuditLog);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);


// individual permission test
perm = perm.Modify(viewChannel: true);
Assert.True(perm.ViewChannel);
Assert.Equal((ulong)GuildPermission.ViewChannel, perm.RawValue);

perm = perm.Modify(viewChannel: false);
Assert.False(perm.ViewChannel);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);


// individual permission test
perm = perm.Modify(sendMessages: true);
Assert.True(perm.SendMessages);
Assert.Equal((ulong)GuildPermission.SendMessages, perm.RawValue);

perm = perm.Modify(sendMessages: false);
Assert.False(perm.SendMessages);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(embedLinks: true);
Assert.True(perm.EmbedLinks);
Assert.Equal((ulong)GuildPermission.EmbedLinks, perm.RawValue);

perm = perm.Modify(embedLinks: false);
Assert.False(perm.EmbedLinks);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(attachFiles: true);
Assert.True(perm.AttachFiles);
Assert.Equal((ulong)GuildPermission.AttachFiles, perm.RawValue);

perm = perm.Modify(attachFiles: false);
Assert.False(perm.AttachFiles);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(readMessageHistory: true);
Assert.True(perm.ReadMessageHistory);
Assert.Equal((ulong)GuildPermission.ReadMessageHistory, perm.RawValue);

perm = perm.Modify(readMessageHistory: false);
Assert.False(perm.ReadMessageHistory);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(mentionEveryone: true);
Assert.True(perm.MentionEveryone);
Assert.Equal((ulong)GuildPermission.MentionEveryone, perm.RawValue);

perm = perm.Modify(mentionEveryone: false);
Assert.False(perm.MentionEveryone);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(useExternalEmojis: true);
Assert.True(perm.UseExternalEmojis);
Assert.Equal((ulong)GuildPermission.UseExternalEmojis, perm.RawValue);

perm = perm.Modify(useExternalEmojis: false);
Assert.False(perm.UseExternalEmojis);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(connect: true);
Assert.True(perm.Connect);
Assert.Equal((ulong)GuildPermission.Connect, perm.RawValue);

perm = perm.Modify(connect: false);
Assert.False(perm.Connect);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(speak: true);
Assert.True(perm.Speak);
Assert.Equal((ulong)GuildPermission.Speak, perm.RawValue);

perm = perm.Modify(speak: false);
Assert.False(perm.Speak);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(muteMembers: true);
Assert.True(perm.MuteMembers);
Assert.Equal((ulong)GuildPermission.MuteMembers, perm.RawValue);

perm = perm.Modify(muteMembers: false);
Assert.False(perm.MuteMembers);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(deafenMembers: true);
Assert.True(perm.DeafenMembers);
Assert.Equal((ulong)GuildPermission.DeafenMembers, perm.RawValue);

perm = perm.Modify(deafenMembers: false);
Assert.False(perm.DeafenMembers);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(moveMembers: true);
Assert.True(perm.MoveMembers);
Assert.Equal((ulong)GuildPermission.MoveMembers, perm.RawValue);

perm = perm.Modify(moveMembers: false);
Assert.False(perm.MoveMembers);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(useVoiceActivation: true);
Assert.True(perm.UseVAD);
Assert.Equal((ulong)GuildPermission.UseVAD, perm.RawValue);

perm = perm.Modify(useVoiceActivation: false);
Assert.False(perm.UseVAD);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(changeNickname: true);
Assert.True(perm.ChangeNickname);
Assert.Equal((ulong)GuildPermission.ChangeNickname, perm.RawValue);

perm = perm.Modify(changeNickname: false);
Assert.False(perm.ChangeNickname);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(manageNicknames: true);
Assert.True(perm.ManageNicknames);
Assert.Equal((ulong)GuildPermission.ManageNicknames, perm.RawValue);

perm = perm.Modify(manageNicknames: false);
Assert.False(perm.ManageNicknames);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(manageRoles: true);
Assert.True(perm.ManageRoles);
Assert.Equal((ulong)GuildPermission.ManageRoles, perm.RawValue);

perm = perm.Modify(manageRoles: false);
Assert.False(perm.ManageRoles);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(manageWebhooks: true);
Assert.True(perm.ManageWebhooks);
Assert.Equal((ulong)GuildPermission.ManageWebhooks, perm.RawValue);

perm = perm.Modify(manageWebhooks: false);
Assert.False(perm.ManageWebhooks);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

// individual permission test
perm = perm.Modify(manageEmojis: true);
Assert.True(perm.ManageEmojis);
Assert.Equal((ulong)GuildPermission.ManageEmojis, perm.RawValue);

perm = perm.Modify(manageEmojis: false);
Assert.False(perm.ManageEmojis);
Assert.Equal(GuildPermissions.None.RawValue, perm.RawValue);

return Task.CompletedTask;
}

}
}
#endif

+ 0
- 73
test/Discord.Net.Tests/Tests.Migrations.cs View File

@@ -1,73 +0,0 @@
using System;
using System.Threading.Tasks;
using Discord.Rest;
#if IXTEST
namespace Discord
{
public partial class TestsFixture
{
public const uint MigrationCount = 3;

public async Task MigrateAsync()
{
DiscordRestClient client = null;
RestGuild guild = null;

await _cache.LoadInfoAsync(_config.GuildId).ConfigureAwait(false);
while (_cache.Info.Version != MigrationCount)
{
if (client == null)
{
client = new DiscordRestClient();
await client.LoginAsync(TokenType.Bot, _config.Token).ConfigureAwait(false);
guild = await client.GetGuildAsync(_config.GuildId);
}

uint nextVer = _cache.Info.Version + 1;
try
{
await DoMigrateAsync(client, guild, nextVer).ConfigureAwait(false);
_cache.Info.Version = nextVer;
await _cache.SaveInfoAsync().ConfigureAwait(false);
}
catch
{
await _cache.ClearAsync().ConfigureAwait(false);
throw;
}
}
}

private static Task DoMigrateAsync(DiscordRestClient client, RestGuild guild, uint toVersion)
{
switch (toVersion)
{
case 1: return Migration_WipeGuild(client, guild);
case 2: return Tests.Migration_CreateTextChannels(client, guild);
case 3: return Tests.Migration_CreateVoiceChannels(client, guild);
default: throw new InvalidOperationException("Unknown migration: " + toVersion);
}
}

private static async Task Migration_WipeGuild(DiscordRestClient client, RestGuild guild)
{
var textChannels = await guild.GetTextChannelsAsync();
var voiceChannels = await guild.GetVoiceChannelsAsync();
var roles = guild.Roles;
foreach (var channel in textChannels)
{
//if (channel.Id != guild.DefaultChannelId)
await channel.DeleteAsync();
}
foreach (var channel in voiceChannels)
await channel.DeleteAsync();
foreach (var role in roles)
{
if (role.Id != guild.EveryoneRole.Id)
await role.DeleteAsync();
}
}
}
}
#endif

+ 0
- 772
test/Discord.Net.Tests/Tests.Permissions.cs View File

@@ -1,772 +0,0 @@
using System.Threading.Tasks;
using Xunit;

namespace Discord
{
public class PermissionsTests
{
private void TestHelper(ChannelPermissions value, ChannelPermission permission, bool expected = false)
=> TestHelper(value.RawValue, (ulong)permission, expected);

private void TestHelper(GuildPermissions value, GuildPermission permission, bool expected = false)
=> TestHelper(value.RawValue, (ulong)permission, expected);

/// <summary>
/// Tests the flag of the given permissions value to the expected output
/// and then tries to toggle the flag on and off
/// </summary>
/// <param name="rawValue"></param>
/// <param name="flagValue"></param>
/// <param name="expected"></param>
private void TestHelper(ulong rawValue, ulong flagValue, bool expected)
{
Assert.Equal(expected, Permissions.GetValue(rawValue, flagValue));

// check that toggling the bit works
Permissions.UnsetFlag(ref rawValue, flagValue);
Assert.False(Permissions.GetValue(rawValue, flagValue));
Permissions.SetFlag(ref rawValue, flagValue);
Assert.True(Permissions.GetValue(rawValue, flagValue));

// do the same, but with the SetValue method
Permissions.SetValue(ref rawValue, true, flagValue);
Assert.True(Permissions.GetValue(rawValue, flagValue));
Permissions.SetValue(ref rawValue, false, flagValue);
Assert.False(Permissions.GetValue(rawValue, flagValue));
}

/// <summary>
/// Tests that flag of the given permissions value to be the expected output
/// and then tries cycling through the states of the allow and deny values
/// for that flag
/// </summary>
/// <param name="value"></param>
/// <param name="flag"></param>
/// <param name="expected"></param>
private void TestHelper(OverwritePermissions value, ChannelPermission flag, PermValue expected)
{
// check that the value matches
Assert.Equal(expected, Permissions.GetValue(value.AllowValue, value.DenyValue, flag));

// check toggling bits for both allow and deny
// have to make copies to get around read only property
ulong allow = value.AllowValue;
ulong deny = value.DenyValue;

// both unset should be inherit
Permissions.UnsetFlag(ref allow, (ulong)flag);
Permissions.UnsetFlag(ref deny, (ulong)flag);
Assert.Equal(PermValue.Inherit, Permissions.GetValue(allow, deny, flag));

// allow set should be allow
Permissions.SetFlag(ref allow, (ulong)flag);
Permissions.UnsetFlag(ref deny, (ulong)flag);
Assert.Equal(PermValue.Allow, Permissions.GetValue(allow, deny, flag));

// deny should be deny
Permissions.UnsetFlag(ref allow, (ulong)flag);
Permissions.SetFlag(ref deny, (ulong)flag);
Assert.Equal(PermValue.Deny, Permissions.GetValue(allow, deny, flag));

// allow takes precedence
Permissions.SetFlag(ref allow, (ulong)flag);
Permissions.SetFlag(ref deny, (ulong)flag);
Assert.Equal(PermValue.Allow, Permissions.GetValue(allow, deny, flag));
}

/// <summary>
/// Tests for the <see cref="Discord.Permissions"/> class.
///
/// Tests that text channel permissions get the right value
/// from the Has method.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestPermissionsHasChannelPermissionText()
{
var value = ChannelPermissions.Text;
// check that the result of GetValue matches for all properties of text channel
TestHelper(value, ChannelPermission.CreateInstantInvite, true);
TestHelper(value, ChannelPermission.ManageChannels, true);
TestHelper(value, ChannelPermission.AddReactions, true);
TestHelper(value, ChannelPermission.ViewChannel, true);
TestHelper(value, ChannelPermission.SendMessages, true);
TestHelper(value, ChannelPermission.SendTTSMessages, true);
TestHelper(value, ChannelPermission.ManageMessages, true);
TestHelper(value, ChannelPermission.EmbedLinks, true);
TestHelper(value, ChannelPermission.AttachFiles, true);
TestHelper(value, ChannelPermission.ReadMessageHistory, true);
TestHelper(value, ChannelPermission.MentionEveryone, true);
TestHelper(value, ChannelPermission.UseExternalEmojis, true);
TestHelper(value, ChannelPermission.ManageRoles, true);
TestHelper(value, ChannelPermission.ManageWebhooks, true);

TestHelper(value, ChannelPermission.Connect, false);
TestHelper(value, ChannelPermission.Speak, false);
TestHelper(value, ChannelPermission.MuteMembers, false);
TestHelper(value, ChannelPermission.DeafenMembers, false);
TestHelper(value, ChannelPermission.MoveMembers, false);
TestHelper(value, ChannelPermission.UseVAD, false);

return Task.CompletedTask;
}

/// <summary>
/// Tests for the <see cref="Discord.Permissions"/> class.
///
/// Tests that no channel permissions get the right value
/// from the Has method.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestPermissionsHasChannelPermissionNone()
{
// check that none will fail all
var value = ChannelPermissions.None;

TestHelper(value, ChannelPermission.CreateInstantInvite, false);
TestHelper(value, ChannelPermission.ManageChannels, false);
TestHelper(value, ChannelPermission.AddReactions, false);
TestHelper(value, ChannelPermission.ViewChannel, false);
TestHelper(value, ChannelPermission.SendMessages, false);
TestHelper(value, ChannelPermission.SendTTSMessages, false);
TestHelper(value, ChannelPermission.ManageMessages, false);
TestHelper(value, ChannelPermission.EmbedLinks, false);
TestHelper(value, ChannelPermission.AttachFiles, false);
TestHelper(value, ChannelPermission.ReadMessageHistory, false);
TestHelper(value, ChannelPermission.MentionEveryone, false);
TestHelper(value, ChannelPermission.UseExternalEmojis, false);
TestHelper(value, ChannelPermission.ManageRoles, false);
TestHelper(value, ChannelPermission.ManageWebhooks, false);
TestHelper(value, ChannelPermission.Connect, false);
TestHelper(value, ChannelPermission.Speak, false);
TestHelper(value, ChannelPermission.MuteMembers, false);
TestHelper(value, ChannelPermission.DeafenMembers, false);
TestHelper(value, ChannelPermission.MoveMembers, false);
TestHelper(value, ChannelPermission.UseVAD, false);

return Task.CompletedTask;
}

/// <summary>
/// Tests for the <see cref="Discord.Permissions"/> class.
///
/// Tests that the dm channel permissions get the right value
/// from the Has method.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestPermissionsHasChannelPermissionDM()
{
// check that none will fail all
var value = ChannelPermissions.DM;

TestHelper(value, ChannelPermission.CreateInstantInvite, false);
TestHelper(value, ChannelPermission.ManageChannels, false);
TestHelper(value, ChannelPermission.AddReactions, false);
TestHelper(value, ChannelPermission.ViewChannel, true);
TestHelper(value, ChannelPermission.SendMessages, true);
TestHelper(value, ChannelPermission.SendTTSMessages, false);
TestHelper(value, ChannelPermission.ManageMessages, false);
TestHelper(value, ChannelPermission.EmbedLinks, true);
TestHelper(value, ChannelPermission.AttachFiles, true);
TestHelper(value, ChannelPermission.ReadMessageHistory, true);
TestHelper(value, ChannelPermission.MentionEveryone, false);
TestHelper(value, ChannelPermission.UseExternalEmojis, true);
TestHelper(value, ChannelPermission.ManageRoles, false);
TestHelper(value, ChannelPermission.ManageWebhooks, false);
TestHelper(value, ChannelPermission.Connect, true);
TestHelper(value, ChannelPermission.Speak, true);
TestHelper(value, ChannelPermission.MuteMembers, false);
TestHelper(value, ChannelPermission.DeafenMembers, false);
TestHelper(value, ChannelPermission.MoveMembers, false);
TestHelper(value, ChannelPermission.UseVAD, true);

return Task.CompletedTask;
}

/// <summary>
/// Tests for the <see cref="Discord.Permissions"/> class.
///
/// Tests that the group channel permissions get the right value
/// from the Has method.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestPermissionsHasChannelPermissionGroup()
{
var value = ChannelPermissions.Group;

TestHelper(value, ChannelPermission.CreateInstantInvite, false);
TestHelper(value, ChannelPermission.ManageChannels, false);
TestHelper(value, ChannelPermission.AddReactions, false);
TestHelper(value, ChannelPermission.ViewChannel, false);
TestHelper(value, ChannelPermission.SendMessages, true);
TestHelper(value, ChannelPermission.SendTTSMessages, true);
TestHelper(value, ChannelPermission.ManageMessages, false);
TestHelper(value, ChannelPermission.EmbedLinks, true);
TestHelper(value, ChannelPermission.AttachFiles, true);
TestHelper(value, ChannelPermission.ReadMessageHistory, false);
TestHelper(value, ChannelPermission.MentionEveryone, false);
TestHelper(value, ChannelPermission.UseExternalEmojis, false);
TestHelper(value, ChannelPermission.ManageRoles, false);
TestHelper(value, ChannelPermission.ManageWebhooks, false);
TestHelper(value, ChannelPermission.Connect, true);
TestHelper(value, ChannelPermission.Speak, true);
TestHelper(value, ChannelPermission.MuteMembers, false);
TestHelper(value, ChannelPermission.DeafenMembers, false);
TestHelper(value, ChannelPermission.MoveMembers, false);
TestHelper(value, ChannelPermission.UseVAD, true);

return Task.CompletedTask;
}


/// <summary>
/// Tests for the <see cref="Discord.Permissions"/> class.
///
/// Tests that the voice channel permissions get the right value
/// from the Has method.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestPermissionsHasChannelPermissionVoice()
{
// make a flag with all possible values for Voice channel permissions
var value = ChannelPermissions.Voice;

TestHelper(value, ChannelPermission.CreateInstantInvite, true);
TestHelper(value, ChannelPermission.ManageChannels, true);
TestHelper(value, ChannelPermission.AddReactions, false);
TestHelper(value, ChannelPermission.ViewChannel, true);
TestHelper(value, ChannelPermission.SendMessages, false);
TestHelper(value, ChannelPermission.SendTTSMessages, false);
TestHelper(value, ChannelPermission.ManageMessages, false);
TestHelper(value, ChannelPermission.EmbedLinks, false);
TestHelper(value, ChannelPermission.AttachFiles, false);
TestHelper(value, ChannelPermission.ReadMessageHistory, false);
TestHelper(value, ChannelPermission.MentionEveryone, false);
TestHelper(value, ChannelPermission.UseExternalEmojis, false);
TestHelper(value, ChannelPermission.ManageRoles, true);
TestHelper(value, ChannelPermission.ManageWebhooks, false);
TestHelper(value, ChannelPermission.Connect, true);
TestHelper(value, ChannelPermission.Speak, true);
TestHelper(value, ChannelPermission.MuteMembers, true);
TestHelper(value, ChannelPermission.DeafenMembers, true);
TestHelper(value, ChannelPermission.MoveMembers, true);
TestHelper(value, ChannelPermission.UseVAD, true);

return Task.CompletedTask;
}

/// <summary>
/// Tests for the <see cref="Discord.Permissions"/> class.
///
/// Test that that the Has method of <see cref="Discord.GuildPermissions"/>
/// returns the correct value when no permissions are set.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestPermissionsHasGuildPermissionNone()
{
var value = GuildPermissions.None;

TestHelper(value, GuildPermission.CreateInstantInvite, false);
TestHelper(value, GuildPermission.KickMembers, false);
TestHelper(value, GuildPermission.BanMembers, false);
TestHelper(value, GuildPermission.Administrator, false);
TestHelper(value, GuildPermission.ManageChannels, false);
TestHelper(value, GuildPermission.ManageGuild, false);
TestHelper(value, GuildPermission.AddReactions, false);
TestHelper(value, GuildPermission.ViewAuditLog, false);
TestHelper(value, GuildPermission.ViewChannel, false);
TestHelper(value, GuildPermission.SendMessages, false);
TestHelper(value, GuildPermission.SendTTSMessages, false);
TestHelper(value, GuildPermission.ManageMessages, false);
TestHelper(value, GuildPermission.EmbedLinks, false);
TestHelper(value, GuildPermission.AttachFiles, false);
TestHelper(value, GuildPermission.ReadMessageHistory, false);
TestHelper(value, GuildPermission.MentionEveryone, false);
TestHelper(value, GuildPermission.UseExternalEmojis, false);
TestHelper(value, GuildPermission.Connect, false);
TestHelper(value, GuildPermission.Speak, false);
TestHelper(value, GuildPermission.MuteMembers, false);
TestHelper(value, GuildPermission.MoveMembers, false);
TestHelper(value, GuildPermission.UseVAD, false);
TestHelper(value, GuildPermission.ChangeNickname, false);
TestHelper(value, GuildPermission.ManageNicknames, false);
TestHelper(value, GuildPermission.ManageRoles, false);
TestHelper(value, GuildPermission.ManageWebhooks, false);
TestHelper(value, GuildPermission.ManageEmojis, false);

return Task.CompletedTask;
}

/// <summary>
/// Tests for the <see cref="Discord.Permissions"/> class.
///
/// Test that that the Has method of <see cref="Discord.GuildPermissions"/>
/// returns the correct value when all permissions are set.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestPermissionsHasGuildPermissionAll()
{
var value = GuildPermissions.All;

TestHelper(value, GuildPermission.CreateInstantInvite, true);
TestHelper(value, GuildPermission.KickMembers, true);
TestHelper(value, GuildPermission.BanMembers, true);
TestHelper(value, GuildPermission.Administrator, true);
TestHelper(value, GuildPermission.ManageChannels, true);
TestHelper(value, GuildPermission.ManageGuild, true);
TestHelper(value, GuildPermission.AddReactions, true);
TestHelper(value, GuildPermission.ViewAuditLog, true);
TestHelper(value, GuildPermission.ViewChannel, true);
TestHelper(value, GuildPermission.SendMessages, true);
TestHelper(value, GuildPermission.SendTTSMessages, true);
TestHelper(value, GuildPermission.ManageMessages, true);
TestHelper(value, GuildPermission.EmbedLinks, true);
TestHelper(value, GuildPermission.AttachFiles, true);
TestHelper(value, GuildPermission.ReadMessageHistory, true);
TestHelper(value, GuildPermission.MentionEveryone, true);
TestHelper(value, GuildPermission.UseExternalEmojis, true);
TestHelper(value, GuildPermission.Connect, true);
TestHelper(value, GuildPermission.Speak, true);
TestHelper(value, GuildPermission.MuteMembers, true);
TestHelper(value, GuildPermission.MoveMembers, true);
TestHelper(value, GuildPermission.UseVAD, true);
TestHelper(value, GuildPermission.ChangeNickname, true);
TestHelper(value, GuildPermission.ManageNicknames, true);
TestHelper(value, GuildPermission.ManageRoles, true);
TestHelper(value, GuildPermission.ManageWebhooks, true);
TestHelper(value, GuildPermission.ManageEmojis, true);


return Task.CompletedTask;
}

/// <summary>
/// Tests for the <see cref="Discord.Permissions"/> class.
///
/// Test that that the Has method of <see cref="Discord.GuildPermissions"/>
/// returns the correct value when webhook permissions are set.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestPermissionsHasGuildPermissionWebhook()
{
var value = GuildPermissions.Webhook;

TestHelper(value, GuildPermission.CreateInstantInvite, false);
TestHelper(value, GuildPermission.KickMembers, false);
TestHelper(value, GuildPermission.BanMembers, false);
TestHelper(value, GuildPermission.Administrator, false);
TestHelper(value, GuildPermission.ManageChannels, false);
TestHelper(value, GuildPermission.ManageGuild, false);
TestHelper(value, GuildPermission.AddReactions, false);
TestHelper(value, GuildPermission.ViewAuditLog, false);
TestHelper(value, GuildPermission.ViewChannel, false);
TestHelper(value, GuildPermission.SendMessages, true);
TestHelper(value, GuildPermission.SendTTSMessages, true);
TestHelper(value, GuildPermission.ManageMessages, false);
TestHelper(value, GuildPermission.EmbedLinks, true);
TestHelper(value, GuildPermission.AttachFiles, true);
TestHelper(value, GuildPermission.ReadMessageHistory, false);
TestHelper(value, GuildPermission.MentionEveryone, false);
TestHelper(value, GuildPermission.UseExternalEmojis, false);
TestHelper(value, GuildPermission.Connect, false);
TestHelper(value, GuildPermission.Speak, false);
TestHelper(value, GuildPermission.MuteMembers, false);
TestHelper(value, GuildPermission.MoveMembers, false);
TestHelper(value, GuildPermission.UseVAD, false);
TestHelper(value, GuildPermission.ChangeNickname, false);
TestHelper(value, GuildPermission.ManageNicknames, false);
TestHelper(value, GuildPermission.ManageRoles, false);
TestHelper(value, GuildPermission.ManageWebhooks, false);
TestHelper(value, GuildPermission.ManageEmojis, false);

return Task.CompletedTask;
}

/// <summary>
/// Test <see cref="Discord.OverwritePermissions"/>
/// for when all text permissions are allowed and denied
/// </summary>
/// <returns></returns>
[Fact]
public Task TestOverwritePermissionsText()
{
// allow all for text channel
var value = new OverwritePermissions(ChannelPermissions.Text.RawValue, ChannelPermissions.None.RawValue);

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Allow);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Allow);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Allow);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Allow);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Allow);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Allow);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Allow);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Allow);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Allow);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Allow);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Allow);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Allow);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Allow);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Allow);
TestHelper(value, ChannelPermission.Connect, PermValue.Inherit);
TestHelper(value, ChannelPermission.Speak, PermValue.Inherit);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Inherit);

value = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Text.RawValue);

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Deny);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Deny);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Deny);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Deny);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Deny);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Deny);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Deny);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Deny);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Deny);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Deny);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Deny);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Deny);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Deny);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Deny);
TestHelper(value, ChannelPermission.Connect, PermValue.Inherit);
TestHelper(value, ChannelPermission.Speak, PermValue.Inherit);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Inherit);

return Task.CompletedTask;
}

/// <summary>
/// Test <see cref="Discord.OverwritePermissions"/>
/// for when none of the permissions are set.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestOverwritePermissionsNone()
{
// allow all for text channel
var value = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.None.RawValue);

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Inherit);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Inherit);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Inherit);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Inherit);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Inherit);
TestHelper(value, ChannelPermission.Connect, PermValue.Inherit);
TestHelper(value, ChannelPermission.Speak, PermValue.Inherit);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Inherit);

value = new OverwritePermissions();

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Inherit);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Inherit);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Inherit);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Inherit);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Inherit);
TestHelper(value, ChannelPermission.Connect, PermValue.Inherit);
TestHelper(value, ChannelPermission.Speak, PermValue.Inherit);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Inherit);

value = OverwritePermissions.InheritAll;

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Inherit);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Inherit);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Inherit);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Inherit);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Inherit);
TestHelper(value, ChannelPermission.Connect, PermValue.Inherit);
TestHelper(value, ChannelPermission.Speak, PermValue.Inherit);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Inherit);

return Task.CompletedTask;
}

/// <summary>
/// Test <see cref="Discord.OverwritePermissions"/>
/// for when all dm permissions are allowed and denied
/// </summary>
/// <returns></returns>
[Fact]
public Task TestOverwritePermissionsDM()
{
// allow all for text channel
var value = new OverwritePermissions(ChannelPermissions.DM.RawValue, ChannelPermissions.None.RawValue);

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Inherit);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Inherit);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Allow);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Allow);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Allow);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Allow);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Allow);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Allow);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Inherit);
TestHelper(value, ChannelPermission.Connect, PermValue.Allow);
TestHelper(value, ChannelPermission.Speak, PermValue.Allow);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Allow);

value = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.DM.RawValue);

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Inherit);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Inherit);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Deny);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Deny);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Deny);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Deny);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Deny);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Deny);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Inherit);
TestHelper(value, ChannelPermission.Connect, PermValue.Deny);
TestHelper(value, ChannelPermission.Speak, PermValue.Deny);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Deny);

return Task.CompletedTask;
}

/// <summary>
/// Test <see cref="Discord.OverwritePermissions"/>
/// for when all group permissions are allowed and denied
/// </summary>
/// <returns></returns>
[Fact]
public Task TestOverwritePermissionsGroup()
{
// allow all for group channels
var value = new OverwritePermissions(ChannelPermissions.Group.RawValue, ChannelPermissions.None.RawValue);

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Inherit);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Inherit);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Allow);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Allow);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Allow);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Allow);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Inherit);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Inherit);
TestHelper(value, ChannelPermission.Connect, PermValue.Allow);
TestHelper(value, ChannelPermission.Speak, PermValue.Allow);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Allow);

value = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Group.RawValue);

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Inherit);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Inherit);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Deny);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Deny);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Deny);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Deny);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Inherit);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Inherit);
TestHelper(value, ChannelPermission.Connect, PermValue.Deny);
TestHelper(value, ChannelPermission.Speak, PermValue.Deny);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Deny);

return Task.CompletedTask;
}

/// <summary>
/// Test <see cref="Discord.OverwritePermissions"/>
/// for when all group permissions are allowed and denied
/// </summary>
/// <returns></returns>
[Fact]
public Task TestOverwritePermissionsVoice()
{
// allow all for group channels
var value = new OverwritePermissions(ChannelPermissions.Voice.RawValue, ChannelPermissions.None.RawValue);

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Allow);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Allow);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Inherit);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Allow);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Inherit);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Inherit);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Allow);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Inherit);
TestHelper(value, ChannelPermission.Connect, PermValue.Allow);
TestHelper(value, ChannelPermission.Speak, PermValue.Allow);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Allow);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Allow);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Allow);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Allow);

value = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Voice.RawValue);

TestHelper(value, ChannelPermission.CreateInstantInvite, PermValue.Deny);
TestHelper(value, ChannelPermission.ManageChannels, PermValue.Deny);
TestHelper(value, ChannelPermission.AddReactions, PermValue.Inherit);
TestHelper(value, ChannelPermission.ViewChannel, PermValue.Deny);
TestHelper(value, ChannelPermission.SendMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.SendTTSMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageMessages, PermValue.Inherit);
TestHelper(value, ChannelPermission.EmbedLinks, PermValue.Inherit);
TestHelper(value, ChannelPermission.AttachFiles, PermValue.Inherit);
TestHelper(value, ChannelPermission.ReadMessageHistory, PermValue.Inherit);
TestHelper(value, ChannelPermission.MentionEveryone, PermValue.Inherit);
TestHelper(value, ChannelPermission.UseExternalEmojis, PermValue.Inherit);
TestHelper(value, ChannelPermission.ManageRoles, PermValue.Deny);
TestHelper(value, ChannelPermission.ManageWebhooks, PermValue.Inherit);
TestHelper(value, ChannelPermission.Connect, PermValue.Deny);
TestHelper(value, ChannelPermission.Speak, PermValue.Deny);
TestHelper(value, ChannelPermission.MuteMembers, PermValue.Deny);
TestHelper(value, ChannelPermission.DeafenMembers, PermValue.Deny);
TestHelper(value, ChannelPermission.MoveMembers, PermValue.Deny);
TestHelper(value, ChannelPermission.UseVAD, PermValue.Deny);

return Task.CompletedTask;
}

/// <summary>
/// Tests for the <see cref="OverwritePermissions.Modify(PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?, PermValue?)"/>
/// method to ensure that the default no-param call does not modify the resulting value
/// of the OverwritePermissions.
/// </summary>
/// <returns></returns>
[Fact]
public Task TestOverwritePermissionModifyNoParam()
{
// test for all Text allowed, none denied
var original = new OverwritePermissions(ChannelPermissions.Text.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, text denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Text.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// category allowed, none denied
original = new OverwritePermissions(ChannelPermissions.Category.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, category denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Category.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// DM allowed, none denied
original = new OverwritePermissions(ChannelPermissions.DM.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, DM denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.DM.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// voice allowed, none denied
original = new OverwritePermissions(ChannelPermissions.Voice.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, voice denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Voice.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// group allowed, none denied
original = new OverwritePermissions(ChannelPermissions.Group.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, group denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.Group.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

// none allowed, none denied
original = new OverwritePermissions(ChannelPermissions.None.RawValue, ChannelPermissions.None.RawValue);
Assert.Equal(original.AllowValue, original.Modify().AllowValue);
Assert.Equal(original.DenyValue, original.Modify().DenyValue);

return Task.CompletedTask;
}
}
}

+ 0
- 133
test/Discord.Net.Tests/Tests.TypeReaders.cs View File

@@ -1,133 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Discord.Commands;
using Xunit;

namespace Discord
{
public sealed class TypeReaderTests
{
[Fact]
public async Task TestNamedArgumentReader()
{
var commands = new CommandService();
var module = await commands.AddModuleAsync<TestModule>(null);

Assert.NotNull(module);
Assert.NotEmpty(module.Commands);

var cmd = module.Commands[0];
Assert.NotNull(cmd);
Assert.NotEmpty(cmd.Parameters);

var param = cmd.Parameters[0];
Assert.NotNull(param);
Assert.True(param.IsRemainder);

var result = await param.ParseAsync(null, "bar: hello foo: 42");
Assert.True(result.IsSuccess);

var m = result.BestMatch as ArgumentType;
Assert.NotNull(m);
Assert.Equal(expected: 42, actual: m.Foo);
Assert.Equal(expected: "hello", actual: m.Bar);
}

[Fact]
public async Task TestQuotedArgumentValue()
{
var commands = new CommandService();
var module = await commands.AddModuleAsync<TestModule>(null);

Assert.NotNull(module);
Assert.NotEmpty(module.Commands);

var cmd = module.Commands[0];
Assert.NotNull(cmd);
Assert.NotEmpty(cmd.Parameters);

var param = cmd.Parameters[0];
Assert.NotNull(param);
Assert.True(param.IsRemainder);

var result = await param.ParseAsync(null, "foo: 42 bar: 《hello》");
Assert.True(result.IsSuccess);

var m = result.BestMatch as ArgumentType;
Assert.NotNull(m);
Assert.Equal(expected: 42, actual: m.Foo);
Assert.Equal(expected: "hello", actual: m.Bar);
}

[Fact]
public async Task TestNonPatternInput()
{
var commands = new CommandService();
var module = await commands.AddModuleAsync<TestModule>(null);

Assert.NotNull(module);
Assert.NotEmpty(module.Commands);

var cmd = module.Commands[0];
Assert.NotNull(cmd);
Assert.NotEmpty(cmd.Parameters);

var param = cmd.Parameters[0];
Assert.NotNull(param);
Assert.True(param.IsRemainder);

var result = await param.ParseAsync(null, "foobar");
Assert.False(result.IsSuccess);
Assert.Equal(expected: CommandError.Exception, actual: result.Error);
}

[Fact]
public async Task TestMultiple()
{
var commands = new CommandService();
var module = await commands.AddModuleAsync<TestModule>(null);

Assert.NotNull(module);
Assert.NotEmpty(module.Commands);

var cmd = module.Commands[0];
Assert.NotNull(cmd);
Assert.NotEmpty(cmd.Parameters);

var param = cmd.Parameters[0];
Assert.NotNull(param);
Assert.True(param.IsRemainder);

var result = await param.ParseAsync(null, "manyints: \"1, 2, 3, 4, 5, 6, 7\"");
Assert.True(result.IsSuccess);

var m = result.BestMatch as ArgumentType;
Assert.NotNull(m);
Assert.Equal(expected: new int[] { 1, 2, 3, 4, 5, 6, 7 }, actual: m.ManyInts);
}
}

[NamedArgumentType]
public sealed class ArgumentType
{
public int Foo { get; set; }

[OverrideTypeReader(typeof(CustomTypeReader))]
public string Bar { get; set; }

public IEnumerable<int> ManyInts { get; set; }
}

public sealed class CustomTypeReader : TypeReader
{
public override Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)
=> Task.FromResult(TypeReaderResult.FromSuccess(input));
}

public sealed class TestModule : ModuleBase
{
[Command("test")]
public Task TestCommand(ArgumentType arg) => Task.Delay(0);
}
}

+ 0
- 55
test/Discord.Net.Tests/Tests.cs View File

@@ -1,55 +0,0 @@
using System;
using Discord.Net;
using Discord.Rest;
using Xunit;
// TODO: re-enable ix testing at a later date
#if IXTEST
namespace Discord
{
public partial class TestsFixture : IDisposable
{
private readonly TestConfig _config;
private readonly CachedRestClient _cache;
internal readonly DiscordRestClient _client;
internal readonly RestGuild _guild;

public TestsFixture()
{
_cache = new CachedRestClient();

_config = TestConfig.LoadFile("./config.json");
var config = new DiscordRestConfig
{
RestClientProvider = url =>
{
_cache.SetUrl(url);
return _cache;
}
};
_client = new DiscordRestClient(config);
_client.LoginAsync(TokenType.Bot, _config.Token).Wait();

MigrateAsync().Wait();
_guild = _client.GetGuildAsync(_config.GuildId).Result;
}

public void Dispose()
{
_client.Dispose();
_cache.Dispose();
}
}

public partial class Tests : IClassFixture<TestsFixture>
{
private DiscordRestClient _client;
private RestGuild _guild;

public Tests(TestsFixture fixture)
{
_client = fixture._client;
_guild = fixture._guild;
}
}
}
#endif

+ 0
- 4
test/Discord.Net.Tests/config.json.example View File

@@ -1,4 +0,0 @@
{
"token": "AAA.BBB.CCC",
"guild_id": 1234567890
}

+ 0
- 4
test/Discord.Net.Tests/xunit.runner.json View File

@@ -1,4 +0,0 @@
{
"diagnosticMessages": true,
"methodDisplay": "classAndMethod"
}

Loading…
Cancel
Save