rpush 1.0.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +99 -0
  3. data/LICENSE +7 -0
  4. data/README.md +189 -0
  5. data/bin/rpush +36 -0
  6. data/config/database.yml +44 -0
  7. data/lib/generators/rpush_generator.rb +44 -0
  8. data/lib/generators/templates/add_adm.rb +23 -0
  9. data/lib/generators/templates/add_alert_is_json_to_rapns_notifications.rb +9 -0
  10. data/lib/generators/templates/add_app_to_rapns.rb +11 -0
  11. data/lib/generators/templates/add_fail_after_to_rpush_notifications.rb +9 -0
  12. data/lib/generators/templates/add_gcm.rb +102 -0
  13. data/lib/generators/templates/add_rpush.rb +349 -0
  14. data/lib/generators/templates/add_wpns.rb +16 -0
  15. data/lib/generators/templates/create_rapns_apps.rb +16 -0
  16. data/lib/generators/templates/create_rapns_feedback.rb +18 -0
  17. data/lib/generators/templates/create_rapns_notifications.rb +29 -0
  18. data/lib/generators/templates/rename_rapns_to_rpush.rb +63 -0
  19. data/lib/generators/templates/rpush.rb +104 -0
  20. data/lib/rpush/TODO +3 -0
  21. data/lib/rpush/adm/app.rb +15 -0
  22. data/lib/rpush/adm/data_validator.rb +11 -0
  23. data/lib/rpush/adm/notification.rb +29 -0
  24. data/lib/rpush/apns/app.rb +29 -0
  25. data/lib/rpush/apns/binary_notification_validator.rb +12 -0
  26. data/lib/rpush/apns/device_token_format_validator.rb +12 -0
  27. data/lib/rpush/apns/feedback.rb +16 -0
  28. data/lib/rpush/apns/notification.rb +84 -0
  29. data/lib/rpush/apns_feedback.rb +13 -0
  30. data/lib/rpush/app.rb +18 -0
  31. data/lib/rpush/configuration.rb +75 -0
  32. data/lib/rpush/daemon/adm/delivery.rb +222 -0
  33. data/lib/rpush/daemon/adm.rb +9 -0
  34. data/lib/rpush/daemon/apns/certificate_expired_error.rb +20 -0
  35. data/lib/rpush/daemon/apns/delivery.rb +64 -0
  36. data/lib/rpush/daemon/apns/disconnection_error.rb +20 -0
  37. data/lib/rpush/daemon/apns/feedback_receiver.rb +79 -0
  38. data/lib/rpush/daemon/apns.rb +16 -0
  39. data/lib/rpush/daemon/app_runner.rb +187 -0
  40. data/lib/rpush/daemon/batch.rb +115 -0
  41. data/lib/rpush/daemon/constants.rb +59 -0
  42. data/lib/rpush/daemon/delivery.rb +28 -0
  43. data/lib/rpush/daemon/delivery_error.rb +19 -0
  44. data/lib/rpush/daemon/dispatcher/http.rb +21 -0
  45. data/lib/rpush/daemon/dispatcher/tcp.rb +30 -0
  46. data/lib/rpush/daemon/dispatcher_loop.rb +54 -0
  47. data/lib/rpush/daemon/dispatcher_loop_collection.rb +33 -0
  48. data/lib/rpush/daemon/feeder.rb +68 -0
  49. data/lib/rpush/daemon/gcm/delivery.rb +222 -0
  50. data/lib/rpush/daemon/gcm.rb +9 -0
  51. data/lib/rpush/daemon/interruptible_sleep.rb +61 -0
  52. data/lib/rpush/daemon/loggable.rb +31 -0
  53. data/lib/rpush/daemon/reflectable.rb +13 -0
  54. data/lib/rpush/daemon/retry_header_parser.rb +23 -0
  55. data/lib/rpush/daemon/retryable_error.rb +20 -0
  56. data/lib/rpush/daemon/service_config_methods.rb +33 -0
  57. data/lib/rpush/daemon/store/active_record/reconnectable.rb +68 -0
  58. data/lib/rpush/daemon/store/active_record.rb +154 -0
  59. data/lib/rpush/daemon/tcp_connection.rb +143 -0
  60. data/lib/rpush/daemon/too_many_requests_error.rb +20 -0
  61. data/lib/rpush/daemon/wpns/delivery.rb +132 -0
  62. data/lib/rpush/daemon/wpns.rb +9 -0
  63. data/lib/rpush/daemon.rb +140 -0
  64. data/lib/rpush/deprecatable.rb +23 -0
  65. data/lib/rpush/deprecation.rb +23 -0
  66. data/lib/rpush/embed.rb +28 -0
  67. data/lib/rpush/gcm/app.rb +11 -0
  68. data/lib/rpush/gcm/expiry_collapse_key_mutual_inclusion_validator.rb +11 -0
  69. data/lib/rpush/gcm/notification.rb +30 -0
  70. data/lib/rpush/logger.rb +63 -0
  71. data/lib/rpush/multi_json_helper.rb +16 -0
  72. data/lib/rpush/notification.rb +69 -0
  73. data/lib/rpush/notifier.rb +52 -0
  74. data/lib/rpush/payload_data_size_validator.rb +10 -0
  75. data/lib/rpush/push.rb +16 -0
  76. data/lib/rpush/railtie.rb +11 -0
  77. data/lib/rpush/reflection.rb +58 -0
  78. data/lib/rpush/registration_ids_count_validator.rb +10 -0
  79. data/lib/rpush/version.rb +3 -0
  80. data/lib/rpush/wpns/app.rb +9 -0
  81. data/lib/rpush/wpns/notification.rb +26 -0
  82. data/lib/rpush.rb +62 -0
  83. data/lib/tasks/cane.rake +18 -0
  84. data/lib/tasks/rpush.rake +16 -0
  85. data/lib/tasks/test.rake +38 -0
  86. data/spec/functional/adm_spec.rb +43 -0
  87. data/spec/functional/apns_spec.rb +58 -0
  88. data/spec/functional/embed_spec.rb +49 -0
  89. data/spec/functional/gcm_spec.rb +42 -0
  90. data/spec/functional/wpns_spec.rb +41 -0
  91. data/spec/support/cert_with_password.pem +90 -0
  92. data/spec/support/cert_without_password.pem +59 -0
  93. data/spec/support/install.sh +32 -0
  94. data/spec/support/simplecov_helper.rb +20 -0
  95. data/spec/support/simplecov_quality_formatter.rb +8 -0
  96. data/spec/tmp/.gitkeep +0 -0
  97. data/spec/unit/adm/app_spec.rb +58 -0
  98. data/spec/unit/adm/notification_spec.rb +45 -0
  99. data/spec/unit/apns/app_spec.rb +29 -0
  100. data/spec/unit/apns/feedback_spec.rb +9 -0
  101. data/spec/unit/apns/notification_spec.rb +208 -0
  102. data/spec/unit/apns_feedback_spec.rb +21 -0
  103. data/spec/unit/app_spec.rb +30 -0
  104. data/spec/unit/configuration_spec.rb +45 -0
  105. data/spec/unit/daemon/adm/delivery_spec.rb +243 -0
  106. data/spec/unit/daemon/apns/certificate_expired_error_spec.rb +11 -0
  107. data/spec/unit/daemon/apns/delivery_spec.rb +101 -0
  108. data/spec/unit/daemon/apns/disconnection_error_spec.rb +18 -0
  109. data/spec/unit/daemon/apns/feedback_receiver_spec.rb +117 -0
  110. data/spec/unit/daemon/app_runner_spec.rb +292 -0
  111. data/spec/unit/daemon/batch_spec.rb +232 -0
  112. data/spec/unit/daemon/delivery_error_spec.rb +13 -0
  113. data/spec/unit/daemon/delivery_spec.rb +38 -0
  114. data/spec/unit/daemon/dispatcher/http_spec.rb +33 -0
  115. data/spec/unit/daemon/dispatcher/tcp_spec.rb +38 -0
  116. data/spec/unit/daemon/dispatcher_loop_collection_spec.rb +37 -0
  117. data/spec/unit/daemon/dispatcher_loop_spec.rb +71 -0
  118. data/spec/unit/daemon/feeder_spec.rb +98 -0
  119. data/spec/unit/daemon/gcm/delivery_spec.rb +310 -0
  120. data/spec/unit/daemon/interruptible_sleep_spec.rb +68 -0
  121. data/spec/unit/daemon/reflectable_spec.rb +27 -0
  122. data/spec/unit/daemon/retryable_error_spec.rb +14 -0
  123. data/spec/unit/daemon/service_config_methods_spec.rb +33 -0
  124. data/spec/unit/daemon/store/active_record/reconnectable_spec.rb +114 -0
  125. data/spec/unit/daemon/store/active_record_spec.rb +357 -0
  126. data/spec/unit/daemon/tcp_connection_spec.rb +287 -0
  127. data/spec/unit/daemon/too_many_requests_error_spec.rb +14 -0
  128. data/spec/unit/daemon/wpns/delivery_spec.rb +159 -0
  129. data/spec/unit/daemon_spec.rb +159 -0
  130. data/spec/unit/deprecatable_spec.rb +32 -0
  131. data/spec/unit/deprecation_spec.rb +15 -0
  132. data/spec/unit/embed_spec.rb +50 -0
  133. data/spec/unit/gcm/app_spec.rb +4 -0
  134. data/spec/unit/gcm/notification_spec.rb +36 -0
  135. data/spec/unit/logger_spec.rb +127 -0
  136. data/spec/unit/notification_shared.rb +105 -0
  137. data/spec/unit/notification_spec.rb +15 -0
  138. data/spec/unit/notifier_spec.rb +49 -0
  139. data/spec/unit/push_spec.rb +43 -0
  140. data/spec/unit/reflection_spec.rb +30 -0
  141. data/spec/unit/rpush_spec.rb +9 -0
  142. data/spec/unit/wpns/app_spec.rb +4 -0
  143. data/spec/unit/wpns/notification_spec.rb +30 -0
  144. data/spec/unit_spec_helper.rb +101 -0
  145. metadata +304 -0
@@ -0,0 +1,90 @@
1
+ Bag Attributes
2
+ localKeyID: A4 1A DB 3E 3E 45 D9 C7 51 1E E6 DC 4E BC 29 19 E4 22 95 35
3
+ subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd
4
+ issuer=/C=UK/ST=Some-State/O=Internet Widgits Pty Ltd
5
+ -----BEGIN CERTIFICATE-----
6
+ MIIE/jCCAuYCAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCVUsxEzARBgNV
7
+ BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
8
+ ZDAeFw0xMjEyMjgxMzU4NTdaFw0xNDEyMjgxMzU4NTdaMEUxCzAJBgNVBAYTAkFV
9
+ MRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRz
10
+ IFB0eSBMdGQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDYCSfYP0P7
11
+ F+JbxUHYsl/9Plr2bFZGMBygqs5RWpw1X977p4FqcNtnRmGENQ/I5vE3KkAKCAlS
12
+ gmus7CjB9/FVzoJq65cT3wBkcqAAzPgIQuI0UjP+rLktV84eUup7Pt6f/Bmt/fBj
13
+ h3fvf80nBQcdK2ztu1xtTs7EsRgyudUDDEIUZw9ddK21RbCMYE0PFY0QapNVvevs
14
+ 8lDVUJX60bZqVqzhvlTzmEaBF+E66J/DhHuhcWZV588hVKjHMNED9Aq4PxRy78vI
15
+ 54v1buX2Y9C6dHfIzfu7zz0Zv5NAY1BZKpaglVGKArOrX+K6O7Bq+DwckTm1AbUf
16
+ pQqi10ghveOtVrm4GXJ4OYW8ohdYKMFjzwhgTTr/NQ+EVlcZ+8AOPVPPJk0HgPu/
17
+ eMNiLytvcSnB09OzIUAzcxOof2a1zfxn7aPzBTEC6kkoDJC/BDG8wxySUz0zRyyM
18
+ jUN2+J1mBJZX1h1sM/4ycAzsX1EYm2II5GGJaFngiV45Qv7wTC7W31kvih7FsdUX
19
+ rEYMkevB5AFPUtIvzevLUObLbPW4yWvU2CMcKLZdIaPTvtPMba91t1YOdufpPRDd
20
+ HTmT42h0aUWDSrcWDAuZPPPqEIQNjRVCudtHtobZDeaUfvbx05CvypyuNFaPonuQ
21
+ l5h0LpZWPetvfsrOlMxPm2kfVcxm8mWjzQIDAQABMA0GCSqGSIb3DQEBBQUAA4IC
22
+ AQBiwdPfLU0kjbU1hM6grUHduLqOPDqLT5gefGRrL5fDqb86G08+Wz+Tnn1YmH+7
23
+ rfiQhCrdi4zxRv6ZEaKZeEm/q1UMttuUdXuzd25BEEtav4R0POdR+H1q3trlS0ol
24
+ EcWlAbRgVaT2tTyKGAW54fH8vZPqS6IP+mXIzfaOFECPEgAO8BL8t7hBDpkL4ASO
25
+ HbU7ktYamsr6PAei3kXAnJ1thXyQqrhelwLrQJyM8RVOJYUgVbl6Fpdtgu7YQF5G
26
+ kxTAfshSmDCQkf+tbUEs44rZ6BZ2TWnbXjQGkRntHcMCP/1rjsPPdX3oeZ7P3jMQ
27
+ XER3drdm1mOiSdDUKbem9GzQ9Dx7WkwKNLYAZ+IWzVRACzGxnkxXyxOEFIgesDgg
28
+ RIhczN+eLIR8iwcUxEVKFmmsbEIve3Uh1/NE6xGudbfZDNfhyOhiNYIBnQqVkk8l
29
+ c3gw2UDR3lXTayiiXhK2l1etsyxtYncT3pgDsCe72RODrGKbASt3FzfBbalzN0GG
30
+ 9tiPSNtGqCch9q4eHfViUh9s3+8n4bknAYcwzQ96+gMEn8PUVtDBv9F8Kxffn/Jt
31
+ XMWKX76nTVuAuCLkXxrKwc01lq8SeuvCH650xsv0LBvxj9h6vR34vHGrj0C3sH2E
32
+ VQpelKNv8IEwkSiQcwDtU8H0jaPJNqmYlkrxasSrSeg6PA==
33
+ -----END CERTIFICATE-----
34
+ Bag Attributes
35
+ localKeyID: A4 1A DB 3E 3E 45 D9 C7 51 1E E6 DC 4E BC 29 19 E4 22 95 35
36
+ Key Attributes: <No Attributes>
37
+ -----BEGIN RSA PRIVATE KEY-----
38
+ Proc-Type: 4,ENCRYPTED
39
+ DEK-Info: DES-EDE3-CBC,874F2C982467BF08
40
+
41
+ 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
90
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,59 @@
1
+ Bag Attributes
2
+ friendlyName: test certificate
3
+ localKeyID: 00 93 8F E4 A3 C3 75 64 3D 7E EA 14 0B 0A EA DD 15 85 8A D5
4
+ subject=/CN=test certificate/O=Example/OU=Example/ST=QLD/C=AU/L=Example/emailAddress=user@example.com
5
+ issuer=/CN=test certificate/O=Example/OU=Example/ST=QLD/C=AU/L=Example/emailAddress=user@example.com
6
+ -----BEGIN CERTIFICATE-----
7
+ MIID5jCCAs6gAwIBAgIBATALBgkqhkiG9w0BAQswgY0xGTAXBgNVBAMMEHRlc3Qg
8
+ Y2VydGlmaWNhdGUxEDAOBgNVBAoMB0V4YW1wbGUxEDAOBgNVBAsMB0V4YW1wbGUx
9
+ DDAKBgNVBAgMA1FMRDELMAkGA1UEBhMCQVUxEDAOBgNVBAcMB0V4YW1wbGUxHzAd
10
+ BgkqhkiG9w0BCQEWEHVzZXJAZXhhbXBsZS5jb20wHhcNMTIwOTA5MDMxODMyWhcN
11
+ MjIwOTA3MDMxODMyWjCBjTEZMBcGA1UEAwwQdGVzdCBjZXJ0aWZpY2F0ZTEQMA4G
12
+ A1UECgwHRXhhbXBsZTEQMA4GA1UECwwHRXhhbXBsZTEMMAoGA1UECAwDUUxEMQsw
13
+ CQYDVQQGEwJBVTEQMA4GA1UEBwwHRXhhbXBsZTEfMB0GCSqGSIb3DQEJARYQdXNl
14
+ ckBleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKF+
15
+ UDsN1sLen8g+97PNTiWju9+wkSv+H5rQlvb6YFLPx11YvqpK8ms6kFU1OmWeLfmh
16
+ cpsT+bZtKupC7aGPoSG3RXzzf/YUMgs/ZSXA0idZHA6tkReAEzIX6jL5otfPWbaP
17
+ luCTUoVMeP4u9ywk628zlqh9IQHC1Agl0R1xGCpULDk8kn1gPyEisl38wI5aDbzy
18
+ 6lYQGNUKOqt1xfVjtIFe/jyY/v0sxFjIJlRLcAFBuJx4sRV+PwRBkusOQtYwcwpI
19
+ loMxJj+GQe66ueATW81aC4iOU66DAFFEuGzwIwm3bOilimGGQbGb92F339RfmSOo
20
+ TPAvVhsakI3mzESb4lkCAwEAAaNRME8wDgYDVR0PAQH/BAQDAgeAMCAGA1UdJQEB
21
+ /wQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAbBgNVHREEFDASgRB1c2VyQGV4YW1w
22
+ bGUuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQA5UbNR+83ZdI2DiaB4dRmy0V5RDAqJ
23
+ k9+QskcTV4gBTjsOBS46Dw1tI6iTrfTyjYJdnyH0Y2Y2YVWBnvtON41UCZak+4ed
24
+ /IqyzU0dtfZ+frWa0RY4reyl80TwqnzyJfni0nDo4zGGvz70cxyaz2u1BWqwLjqb
25
+ dh8Dxvt+aHW2MQi0iGKh/HNbgwVanR4+ubNwziK9sR1Rnq9MkHWtwBw16SXQG6ao
26
+ SZKASWNaH8VL08Zz0E98cwd137UJkPsldCwJ8kHR5OzkcjPdXvnGD3d64yy2TC1Z
27
+ Gy1Aazt98wPcTYBytlhK8Rvzg9OoY9QmsdpmWxz1ZCXECJNqCa3IKsqO
28
+ -----END CERTIFICATE-----
29
+ Bag Attributes
30
+ friendlyName: test certificate
31
+ localKeyID: 00 93 8F E4 A3 C3 75 64 3D 7E EA 14 0B 0A EA DD 15 85 8A D5
32
+ Key Attributes: <No Attributes>
33
+ -----BEGIN RSA PRIVATE KEY-----
34
+ MIIEpQIBAAKCAQEAoX5QOw3Wwt6fyD73s81OJaO737CRK/4fmtCW9vpgUs/HXVi+
35
+ qkryazqQVTU6ZZ4t+aFymxP5tm0q6kLtoY+hIbdFfPN/9hQyCz9lJcDSJ1kcDq2R
36
+ F4ATMhfqMvmi189Zto+W4JNShUx4/i73LCTrbzOWqH0hAcLUCCXRHXEYKlQsOTyS
37
+ fWA/ISKyXfzAjloNvPLqVhAY1Qo6q3XF9WO0gV7+PJj+/SzEWMgmVEtwAUG4nHix
38
+ FX4/BEGS6w5C1jBzCkiWgzEmP4ZB7rq54BNbzVoLiI5TroMAUUS4bPAjCbds6KWK
39
+ YYZBsZv3YXff1F+ZI6hM8C9WGxqQjebMRJviWQIDAQABAoIBAQCTiLIDQUFSBdAz
40
+ QFNLD+S0vkCEuunlJuP4q1c/ir006l1YChsluBJ/o6D4NwiCjV+zDquEwVsALftm
41
+ yH4PewfZpXT2Ef508T5GyEO/mchj6iSXxDkpHvhqay6qIyWBwwxSnBtaTzy0Soi+
42
+ rmlhCtmLXbXld2sQEM1kJChGnWtWPtvSyrn+mapNPZviGRtgRNK+YsrAti1nUext
43
+ 2syO5mTdHf1D8GR7I98OaX6odREuSocEV9PzfapWZx2GK5tvRiS1skiug5ciieTd
44
+ Am5/C+bb31h4drFslihLb5BRGO5SFQJvMJL2Sx1f19BCC4XikS01P4/zZbxQNq79
45
+ kxEQuDGBAoGBANP4pIYZ5xshCkx7cTYqmxzWLClGKE2S7Oa8N89mtOwfmqT9AFun
46
+ t9Us9Ukbi8BaKlKhGpQ1HlLf/KVcpyW0x2qLou6AyIWYH+/5VaR3graNgUnzpK9f
47
+ 1F5HoaNHbhlAoebqhzhASFlJI2aqUdQjdOv73z+s9szJU4gpILNwGDFnAoGBAMMJ
48
+ j+vIxtG9J2jldyoXzpg5mbMXSj9u/wFLBVdjXWyOoiqVMMBto53RnoqAom7Ifr9D
49
+ 49LxRAT1Q3l4vs/YnM3ziMsIg2vQK1EbrLsY9OnD/kvPaLXOlNIOdfLM8UeVWZMc
50
+ I4LPbbZrhv/7CC8RjbRhMoWWdGYPvxmvD6V4ZDY/AoGBALoI6OxA45Htx4okdNHj
51
+ RstiNNPsnQaoQn6nBhxiubraafEPkzbd1fukP4pwQJELEUX/2sHkdL6rkqLW1GPF
52
+ a5dZAiBsqpCFWNJWdBGqSfBJ9QSgbxLz+gDcwUH6OOi0zuNJRm/aCyVBiW5bYQHc
53
+ NIvAPMk31ksZDtTbs7WIVdNVAoGBALZ1+KWNxKqs+fSBT5UahpUUtfy8miJz9a7A
54
+ /3M8q0cGvSF3Rw+OwpW/aEGMi+l2OlU27ykFuyukRAac9m296RwnbF79TO2M5ylO
55
+ 6a5zb5ROXlWP6RbE96b4DlIidssQJqegmHwlEC+rsrVBpOtb0aThlYEyOxzMOGyP
56
+ wOR9l8rDAoGADZ4TUHFM6VrvPlUZBkGbqiyXH9IM/y9JWk+22JQCEGnM6RFZemSs
57
+ jxWqQiPAdJtb3xKryJSCMtFPH9azedoCrSgaMflJ1QgoXgpiKZyoEXWraVUggh/0
58
+ CEavgZcTZ6SvMuayqJdGGB+zb1V8XwXMtCjApR/kTm47DjxO4DmpOPs=
59
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,32 @@
1
+ cp -R /mnt/rpush /rpush
2
+ gem install --no-ri --no-rdoc rails
3
+ cd /tmp
4
+ export HOME=/
5
+ export RAILS_NAME=rpush_`date +"%Y%m%d%H%M%S"`
6
+ rails new $RAILS_NAME -BJTS -d mysql
7
+ cd $RAILS_NAME
8
+ for gem in sdoc coffee-rails uglifier sass-rails jquery-rails jbuilder turbolinks
9
+ do
10
+ sed -i.bak -e "s/^gem '$gem'/\# gem '$gem'/g" Gemfile
11
+ done
12
+ echo 'gem "rpush", path: "/rpush"' >> Gemfile
13
+ bundle
14
+ /etc/init.d/mysql start
15
+ mysqladmin create `echo $RAILS_NAME`_development
16
+ rails g rpush
17
+ rake db:migrate
18
+ cat > create_app.rb <<EOF
19
+ app = Rpush::Gcm::App.new
20
+ app.name = "android_app"
21
+ app.auth_key = "123"
22
+ app.save!
23
+
24
+ n = Rpush::Gcm::Notification.new
25
+ n.app = app
26
+ n.registration_ids = ["abc"]
27
+ n.data = {:message => "hi mom!"}
28
+ n.save!
29
+ EOF
30
+ rails runner create_app.rb
31
+ export RPUSH_GCM_HOST=http://`/sbin/ip route | awk '/default/ { print $3 }'`
32
+ rpush development -f
@@ -0,0 +1,20 @@
1
+ require 'simplecov'
2
+ require './spec/support/simplecov_quality_formatter'
3
+
4
+ module SimpleCovHelper
5
+ def start_simple_cov(name)
6
+ SimpleCov.start do
7
+ add_filter '/spec/'
8
+ add_filter '/lib/generators'
9
+ command_name name
10
+
11
+ if ENV['TRAVIS']
12
+ require 'coveralls'
13
+ formatter SimpleCov::Formatter::MultiFormatter[SimpleCov::Formatter::QualityFormatter,
14
+ Coveralls::SimpleCov::Formatter]
15
+ else
16
+ formatter SimpleCov::Formatter::QualityFormatter
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ class SimpleCov::Formatter::QualityFormatter
2
+ def format(result)
3
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
4
+ File.open("coverage/covered_percent", "w") do |f|
5
+ f.puts result.source_files.covered_percent.to_f
6
+ end
7
+ end
8
+ end
data/spec/tmp/.gitkeep ADDED
File without changes
@@ -0,0 +1,58 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::Adm::App do
4
+ subject { Rpush::Adm::App.new(:name => 'test', :environment => 'development', :client_id => 'CLIENT_ID', :client_secret => 'CLIENT_SECRET') }
5
+ let(:existing_app) { Rpush::Adm::App.create!(:name => 'existing', :environment => 'development', :client_id => 'CLIENT_ID', :client_secret => 'CLIENT_SECRET') }
6
+
7
+ it 'should be valid if properly instantiated' do
8
+ subject.should be_valid
9
+ end
10
+
11
+ it 'should be invalid if name' do
12
+ subject.name = nil
13
+ subject.should_not be_valid
14
+ subject.errors[:name].should eq ["can't be blank"]
15
+ end
16
+
17
+ it 'should be invalid if name is not unique within scope' do
18
+ subject.name = existing_app.name
19
+ subject.should_not be_valid
20
+ subject.errors[:name].should eq ["has already been taken"]
21
+ end
22
+
23
+ it 'should be invalid if missing client_id' do
24
+ subject.client_id = nil
25
+ subject.should_not be_valid
26
+ subject.errors[:client_id].should eq ["can't be blank"]
27
+ end
28
+
29
+ it 'should be invalid if missing client_secret' do
30
+ subject.client_secret = nil
31
+ subject.should_not be_valid
32
+ subject.errors[:client_secret].should eq ["can't be blank"]
33
+ end
34
+
35
+ describe '#access_token_expired?' do
36
+ before(:each) do
37
+ Timecop.freeze(Time.now)
38
+ end
39
+
40
+ after do
41
+ Timecop.return
42
+ end
43
+
44
+ it 'should return true if access_token_expiration is nil' do
45
+ subject.access_token_expired?.should be_true
46
+ end
47
+
48
+ it 'should return true if expired' do
49
+ subject.access_token_expiration = Time.now - 5.minutes
50
+ subject.access_token_expired?.should be_true
51
+ end
52
+
53
+ it 'should return false if not expired' do
54
+ subject.access_token_expiration = Time.now + 5.minutes
55
+ subject.access_token_expired?.should be_false
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,45 @@
1
+ require 'unit_spec_helper'
2
+ require 'unit/notification_shared.rb'
3
+
4
+ describe Rpush::Adm::Notification do
5
+ it_should_behave_like 'an Notification subclass'
6
+
7
+ let(:app) { Rpush::Adm::App.create!(:name => 'test', :client_id => 'CLIENT_ID', :client_secret => 'CLIENT_SECRET') }
8
+ let(:notification_class) { Rpush::Adm::Notification }
9
+ let(:notification) { notification_class.new }
10
+ let(:data_setter) { 'data=' }
11
+ let(:data_getter) { 'data' }
12
+
13
+ it "has a 'data' payload limit of 6144 bytes" do
14
+ notification.data = { :key => "a" * 6144 }
15
+ notification.valid?.should be_false
16
+ notification.errors[:base].should eq ["Notification payload data cannot be larger than 6144 bytes."]
17
+ end
18
+
19
+ it 'limits the number of registration ids to 100' do
20
+ notification.registration_ids = ['a']*(100+1)
21
+ notification.valid?.should be_false
22
+ notification.errors[:base].should eq ["Number of registration_ids cannot be larger than 100."]
23
+ end
24
+
25
+ it 'validates data can be blank if collapse_key is set' do
26
+ notification.app = app
27
+ notification.registration_ids = 'a'
28
+ notification.collapse_key = 'test'
29
+ notification.data = nil
30
+ notification.valid?.should be_true
31
+ notification.errors[:data].should be_empty
32
+ end
33
+
34
+ it 'validates data is present if collapse_key is not set' do
35
+ notification.collapse_key = nil
36
+ notification.data = nil
37
+ notification.valid?.should be_false
38
+ notification.errors[:data].should eq ['must be set unless collapse_key is specified']
39
+ end
40
+
41
+ it 'includes expiresAfter in the payload' do
42
+ notification.expiry = 100
43
+ notification.as_json['expiresAfter'].should eq 100
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::App do
4
+ it 'does not validate an app with an invalid certificate' do
5
+ app = Rpush::Apns::App.new(:name => 'test', :environment => 'development', :certificate => 'foo')
6
+ app.valid?
7
+ app.errors[:certificate].should eq ['Certificate value must contain a certificate and a private key.']
8
+ end
9
+
10
+ it 'validates a certificate without a password' do
11
+ app = Rpush::Apns::App.new :name => 'test', :environment => 'development', :certificate => TEST_CERT
12
+ app.valid?
13
+ app.errors[:certificate].should eq []
14
+ end
15
+
16
+ it 'validates a certificate with a password' do
17
+ app = Rpush::Apns::App.new :name => 'test', :environment => 'development',
18
+ :certificate => TEST_CERT_WITH_PASSWORD, :password => 'fubar'
19
+ app.valid?
20
+ app.errors[:certificate].should eq []
21
+ end
22
+
23
+ it 'validates a certificate with an incorrect password' do
24
+ app = Rpush::Apns::App.new :name => 'test', :environment => 'development',
25
+ :certificate => TEST_CERT_WITH_PASSWORD, :password => 'incorrect'
26
+ app.valid?
27
+ app.errors[:certificate].should eq ["Certificate value must contain a certificate and a private key."]
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ require "unit_spec_helper"
2
+
3
+ describe Rpush::Apns::Feedback do
4
+ it "should validate the format of the device_token" do
5
+ notification = Rpush::Apns::Feedback.new(:device_token => "{$%^&*()}")
6
+ notification.valid?.should be_false
7
+ notification.errors[:device_token].include?("is invalid").should be_true
8
+ end
9
+ end
@@ -0,0 +1,208 @@
1
+ # encoding: US-ASCII
2
+
3
+ require "unit_spec_helper"
4
+ require 'unit/notification_shared.rb'
5
+
6
+ describe Rpush::Apns::Notification do
7
+ it_should_behave_like 'an Notification subclass'
8
+
9
+ let(:app) { Rpush::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT) }
10
+ let(:notification_class) { Rpush::Apns::Notification }
11
+ let(:notification) { notification_class.new }
12
+ let(:data_setter) { 'attributes_for_device=' }
13
+ let(:data_getter) { 'attributes_for_device' }
14
+
15
+ it "should validate the format of the device_token" do
16
+ notification = Rpush::Apns::Notification.new(:device_token => "{$%^&*()}")
17
+ notification.valid?.should be_false
18
+ notification.errors[:device_token].include?("is invalid").should be_true
19
+ end
20
+
21
+ it "should validate the length of the binary conversion of the notification" do
22
+ notification.device_token = "a" * 64
23
+ notification.alert = "way too long!" * 100
24
+ notification.valid?.should be_false
25
+ notification.errors[:base].include?("APN notification cannot be larger than 256 bytes. Try condensing your alert and device attributes.").should be_true
26
+ end
27
+
28
+ it "should default the sound to 'default'" do
29
+ notification.sound.should eq('default')
30
+ end
31
+
32
+ it "should default the expiry to 1 day" do
33
+ notification.expiry.should eq 1.day.to_i
34
+ end
35
+ end
36
+
37
+ describe Rpush::Apns::Notification, "when assigning the device token" do
38
+ it "should strip spaces from the given string" do
39
+ notification = Rpush::Apns::Notification.new(:device_token => "o m g")
40
+ notification.device_token.should eq "omg"
41
+ end
42
+
43
+ it "should strip chevrons from the given string" do
44
+ notification = Rpush::Apns::Notification.new(:device_token => "<omg>")
45
+ notification.device_token.should eq "omg"
46
+ end
47
+ end
48
+
49
+ describe Rpush::Apns::Notification, "as_json" do
50
+ it "should include the alert if present" do
51
+ notification = Rpush::Apns::Notification.new(:alert => "hi mom")
52
+ notification.as_json["aps"]["alert"].should eq "hi mom"
53
+ end
54
+
55
+ it "should not include the alert key if the alert is not present" do
56
+ notification = Rpush::Apns::Notification.new(:alert => nil)
57
+ notification.as_json["aps"].key?("alert").should be_false
58
+ end
59
+
60
+ it "should encode the alert as JSON if it is a Hash" do
61
+ notification = Rpush::Apns::Notification.new(:alert => { 'body' => "hi mom", 'alert-loc-key' => "View" })
62
+ notification.as_json["aps"]["alert"].should eq ({ 'body' => "hi mom", 'alert-loc-key' => "View" })
63
+ end
64
+
65
+ it "should include the badge if present" do
66
+ notification = Rpush::Apns::Notification.new(:badge => 6)
67
+ notification.as_json["aps"]["badge"].should eq 6
68
+ end
69
+
70
+ it "should not include the badge key if the badge is not present" do
71
+ notification = Rpush::Apns::Notification.new(:badge => nil)
72
+ notification.as_json["aps"].key?("badge").should be_false
73
+ end
74
+
75
+ it "should include the sound if present" do
76
+ notification = Rpush::Apns::Notification.new(:alert => "my_sound.aiff")
77
+ notification.as_json["aps"]["alert"].should eq "my_sound.aiff"
78
+ end
79
+
80
+ it "should not include the sound key if the sound is not present" do
81
+ notification = Rpush::Apns::Notification.new(:sound => false)
82
+ notification.as_json["aps"].key?("sound").should be_false
83
+ end
84
+
85
+ it "should include attributes for the device" do
86
+ notification = Rpush::Apns::Notification.new
87
+ notification.attributes_for_device = {:omg => :lol, :wtf => :dunno}
88
+ notification.as_json["omg"].should eq "lol"
89
+ notification.as_json["wtf"].should eq "dunno"
90
+ end
91
+
92
+ it "should allow attributes to include a hash" do
93
+ notification = Rpush::Apns::Notification.new
94
+ notification.attributes_for_device = {:omg => {:ilike => :hashes}}
95
+ notification.as_json["omg"]["ilike"].should eq "hashes"
96
+ end
97
+
98
+ end
99
+
100
+ describe Rpush::Apns::Notification, 'MDM' do
101
+ let(:magic) { 'abc123' }
102
+ let(:notification) { Rpush::Apns::Notification.new }
103
+
104
+ it 'includes the mdm magic in the payload' do
105
+ notification.mdm = magic
106
+ notification.as_json.should eq ({'mdm' => magic})
107
+ end
108
+
109
+ it 'does not include aps attribute' do
110
+ notification.alert = "i'm doomed"
111
+ notification.mdm = magic
112
+ notification.as_json.key?('aps').should be_false
113
+ end
114
+ end
115
+
116
+ describe Rpush::Apns::Notification, 'content-available' do
117
+ let(:notification) { Rpush::Apns::Notification.new }
118
+
119
+ it 'includes content-available in the payload' do
120
+ notification.content_available = true
121
+ notification.as_json['aps']['content-available'].should eq 1
122
+ end
123
+
124
+ it 'does not include content-available in the payload if not set' do
125
+ notification.as_json['aps'].key?('content-available').should be_false
126
+ end
127
+
128
+ it 'does not include content-available as a non-aps attribute' do
129
+ notification.content_available = true
130
+ notification.as_json.key?('content-available').should be_false
131
+ end
132
+
133
+ it 'does not overwrite existing attributes for the device' do
134
+ notification.data = {:hi => :mom}
135
+ notification.content_available = true
136
+ notification.as_json['aps']['content-available'].should eq 1
137
+ notification.as_json['hi'].should eq 'mom'
138
+ end
139
+
140
+ it 'does not overwrite the content-available flag when setting attributes for the device' do
141
+ notification.content_available = true
142
+ notification.data = {:hi => :mom}
143
+ notification.as_json['aps']['content-available'].should eq 1
144
+ notification.as_json['hi'].should eq 'mom'
145
+ end
146
+ end
147
+
148
+ describe Rpush::Apns::Notification, "to_binary" do
149
+ it "should correctly convert the notification to binary" do
150
+ notification = Rpush::Apns::Notification.new
151
+ notification.device_token = "a" * 64
152
+ notification.sound = "1.aiff"
153
+ notification.badge = 3
154
+ notification.alert = "Don't panic Mr Mainwaring, don't panic!"
155
+ notification.attributes_for_device = {:hi => :mom}
156
+ notification.expiry = 86400 # 1 day, \x00\x01Q\x80
157
+ notification.app = Rpush::Apns::App.new(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT)
158
+ notification.stub(:id).and_return(1234)
159
+ notification.to_binary.should eq "\x01\x00\x00\x04\xD2\x00\x01Q\x80\x00 \xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\x00a{\"aps\":{\"alert\":\"Don't panic Mr Mainwaring, don't panic!\",\"badge\":3,\"sound\":\"1.aiff\"},\"hi\":\"mom\"}"
160
+ end
161
+ end
162
+
163
+ describe Rpush::Apns::Notification, "bug #31" do
164
+ it 'does not confuse a JSON looking string as JSON' do
165
+ notification = Rpush::Apns::Notification.new
166
+ notification.alert = "{\"one\":2}"
167
+ notification.alert.should eq "{\"one\":2}"
168
+ end
169
+
170
+ it 'does confuse a JSON looking string as JSON if the alert_is_json attribute is not present' do
171
+ notification = Rpush::Apns::Notification.new
172
+ notification.stub(:has_attribute? => false)
173
+ notification.alert = "{\"one\":2}"
174
+ notification.alert.should eq ({"one" => 2})
175
+ end
176
+ end
177
+
178
+ describe Rpush::Apns::Notification, "bug #35" do
179
+ it "should limit payload size to 256 bytes but not the entire packet" do
180
+ notification = Rpush::Apns::Notification.new do |n|
181
+ n.device_token = "a" * 64
182
+ n.alert = "a" * 210
183
+ n.app = Rpush::Apns::App.create!(:name => 'my_app', :environment => 'development', :certificate => TEST_CERT)
184
+ end
185
+
186
+ notification.to_binary(:for_validation => true).bytesize.should > 256
187
+ notification.payload_size.should < 256
188
+ notification.should be_valid
189
+ end
190
+ end
191
+
192
+ describe Rpush::Apns::Notification, "multi_json usage" do
193
+ describe Rpush::Apns::Notification, "alert" do
194
+ it "should call MultiJson.load when multi_json version is 1.3.0" do
195
+ notification = Rpush::Apns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
196
+ Gem.stub(:loaded_specs).and_return( { 'multi_json' => Gem::Specification.new('multi_json', '1.3.0') } )
197
+ MultiJson.should_receive(:load).with(any_args())
198
+ notification.alert
199
+ end
200
+
201
+ it "should call MultiJson.decode when multi_json version is 1.2.9" do
202
+ notification = Rpush::Apns::Notification.new(:alert => { :a => 1 }, :alert_is_json => true)
203
+ Gem.stub(:loaded_specs).and_return( { 'multi_json' => Gem::Specification.new('multi_json', '1.2.9') } )
204
+ MultiJson.should_receive(:decode).with(any_args())
205
+ notification.alert
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,21 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush, 'apns_feedback' do
4
+ let!(:app) { Rpush::Apns::App.create!(:name => 'test', :environment => 'production', :certificate => TEST_CERT) }
5
+ let(:receiver) { double(:check_for_feedback => nil) }
6
+
7
+ before do
8
+ Rpush::Daemon::Apns::FeedbackReceiver.stub(:new => receiver)
9
+ end
10
+
11
+ it 'initializes the store' do
12
+ Rpush::Daemon.should_receive(:initialize_store)
13
+ Rpush.apns_feedback
14
+ end
15
+
16
+ it 'checks feedback for each app' do
17
+ Rpush::Daemon::Apns::FeedbackReceiver.should_receive(:new).with(app).and_return(receiver)
18
+ receiver.should_receive(:check_for_feedback)
19
+ Rpush.apns_feedback
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush::App do
4
+ it 'validates the uniqueness of name within type and environment' do
5
+ Rpush::Apns::App.create!(:name => 'test', :environment => 'production', :certificate => TEST_CERT)
6
+ app = Rpush::Apns::App.new(:name => 'test', :environment => 'production', :certificate => TEST_CERT)
7
+ app.valid?.should be_false
8
+ app.errors[:name].should eq ['has already been taken']
9
+
10
+ app = Rpush::Apns::App.new(:name => 'test', :environment => 'development', :certificate => TEST_CERT)
11
+ app.valid?.should be_true
12
+
13
+ app = Rpush::Gcm::App.new(:name => 'test', :environment => 'production', :auth_key => TEST_CERT)
14
+ app.valid?.should be_true
15
+ end
16
+
17
+ context 'validating certificates' do
18
+ it 'rescues from certificate error' do
19
+ app = Rpush::Apns::App.new(:name => 'test', :environment => 'development', :certificate => 'bad')
20
+ expect{app.valid?}.not_to raise_error
21
+ expect(app.valid?).to be_false
22
+ end
23
+
24
+ it 'raises other errors' do
25
+ app = Rpush::Apns::App.new(:name => 'test', :environment => 'development', :certificate => 'bad')
26
+ OpenSSL::X509::Certificate.stub(:new).and_raise(NameError, 'simulating no openssl')
27
+ expect{app.valid?}.to raise_error(NameError)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ require 'unit_spec_helper'
2
+
3
+ describe Rpush do
4
+ let(:config) { double }
5
+
6
+ before { Rpush.stub(:config => config) }
7
+
8
+ it 'can yields a config block' do
9
+ expect { |b| Rpush.configure(&b) }.to yield_with_args(config)
10
+ end
11
+ end
12
+
13
+ describe Rpush::Configuration do
14
+ let(:config) do
15
+ Rpush::Deprecation.muted do
16
+ Rpush::Configuration.new
17
+ end
18
+ end
19
+
20
+ it 'can be updated' do
21
+ Rpush::Deprecation.muted do
22
+ new_config = Rpush::Configuration.new
23
+ new_config.batch_size = 200
24
+ expect { config.update(new_config) }.to change(config, :batch_size).to(200)
25
+ end
26
+ end
27
+
28
+ it 'sets the pid_file relative if not absolute' do
29
+ Rails.stub(:root => '/rails')
30
+ config.pid_file = 'tmp/rpush.pid'
31
+ config.pid_file.should eq '/rails/tmp/rpush.pid'
32
+ end
33
+
34
+ it 'does not alter an absolute pid_file path' do
35
+ config.pid_file = '/tmp/rpush.pid'
36
+ config.pid_file.should eq '/tmp/rpush.pid'
37
+ end
38
+
39
+ it 'does not allow foreground to be set to false if the platform is JRuby' do
40
+ config.foreground = true
41
+ Rpush.stub(:jruby? => true)
42
+ config.foreground = false
43
+ config.foreground.should be_true
44
+ end
45
+ end